Skip to main content

Overview

3D shapes in OpenPlans provide volumetric geometry for creating architectural models, furniture, fixtures, and structural elements. These shapes extend from the OpenGeometry kernel and integrate seamlessly with 2D primitives.

Cuboid Shape

Cuboids (rectangular prisms) are the most common 3D shape for modeling walls, beams, columns, and furniture.

Creating Cuboids

import { OpenPlans, Vector3 } from 'openplans';

const openPlans = new OpenPlans(container);
await openPlans.setupOpenGeometry();

// Create a basic cuboid
const cuboid = openPlans.cuboid({
  center: new Vector3(0, 0, 0),
  width: 2,
  height: 1,
  depth: 1,
  color: 0x000000
});

Cuboid Properties

// Access and modify properties through propertySet
const config = cuboid.getOPConfig();

console.log(config);
// {
//   center: Vector3(0, 0, 0),
//   width: 2,
//   height: 1,
//   depth: 1,
//   color: 0x000000,
//   ogid: "uuid-here"
// }

Updating Cuboid Configuration

// Update cuboid using setOPConfig
cuboid.setOPConfig({
  center: new Vector3(5, 0, 5),
  width: 3,
  height: 2,
  depth: 1.5,
  color: 0xFF0000
});

// The geometry is automatically discarded and rebuilt

Preloading Cuboids

const preloadedCuboid = openPlans.cuboid({
  ogid: '86302abc-d71e-47be-affc-dc05de1db8fe',
  center: new Vector3(20, 0, 0),
  width: 20,
  height: 10,
  depth: 1,
  color: 0x000000
});

const config = preloadedCuboid.getOPConfig();
console.log('Preloaded Cuboid:', config);

Cylinder Shape

Cylinders are useful for columns, pipes, curved walls, and decorative elements.

Creating Cylinders

const cylinder = openPlans.cylinder({
  center: new Vector3(0, 1, 0),
  radius: 0.5,
  height: 2,
  segments: 32,  // Higher = smoother
  color: 0x0000FF
});

Cylinder Properties

  • center: Vector3 - Center point of cylinder base
  • radius: number - Cylinder radius
  • height: number - Cylinder height (along Y-axis)
  • segments: number - Number of radial segments (affects smoothness)
  • color: number - Cylinder color

Modifying Cylinders

// Update cylinder configuration
cylinder.setOPConfig({
  center: new Vector3(5, 0, 5),
  radius: 1,
  height: 3,
  segments: 64,
  color: 0x00FF00
});

// Get current configuration
const cylinderConfig = cylinder.getOPConfig();

Working with 3D Shape Configurations

All 3D shapes implement the IShape interface with consistent methods.

Getting Configuration

const cuboidConfig = cuboid.getOPConfig();
const cylinderConfig = cylinder.getOPConfig();

// Configurations can be serialized
const savedConfig = JSON.stringify(cuboidConfig);

Setting Configuration

// Discard old geometry and create new
cuboid.setOPConfig({
  center: new Vector3(10, 0, 10),
  width: 5,
  height: 3,
  depth: 2,
  color: 0xFFFF00
});

// The setOPConfig method:
// 1. Calls discardGeometry() to clean up
// 2. Updates the propertySet
// 3. Calls setConfig() to rebuild geometry

Shape States

All shapes support selection and editing states:
// Selection state
cuboid.selected = true;

// Edit state
cuboid.edit = true;

// Check states
if (cuboid.selected) {
  console.log('Cuboid is selected');
}

Sub-Nodes

3D shapes can have sub-nodes for additional geometry:
// Access sub-nodes map
const subNodes = cuboid.subNodes;

// Add custom geometry as sub-node
const decoration = new THREE.Mesh(
  new THREE.SphereGeometry(0.2),
  new THREE.MeshBasicMaterial({ color: 0xFF0000 })
);

cuboid.subNodes.set('decoration', decoration);
cuboid.add(decoration);

Type Information

console.log(cuboid.ogType);    // "CuboidShape"
console.log(cylinder.ogType);  // "CylinderShape"

// Filter by type
const allCuboids = openPlans.getEntitiesByType('CuboidShape');
const allCylinders = openPlans.getEntitiesByType('CylinderShape');

Practical Examples

Creating a Column

const column = openPlans.cylinder({
  center: new Vector3(0, 1.5, 0),  // Half height up
  radius: 0.3,
  height: 3,
  segments: 32,
  color: 0xCCCCCC
});

Creating a Wall Section

const wall = openPlans.cuboid({
  center: new Vector3(5, 1.5, 0),  // Center at half height
  width: 10,   // Wall length
  height: 3,   // Wall height
  depth: 0.2,  // Wall thickness
  color: 0xEEEEEE
});

Creating a Beam

const beam = openPlans.cuboid({
  center: new Vector3(5, 3, 5),
  width: 10,   // Beam span
  height: 0.4, // Beam depth
  depth: 0.3,  // Beam width
  color: 0x888888
});

Creating a Simple Table

// Table top
const tableTop = openPlans.cuboid({
  center: new Vector3(5, 0.75, 5),
  width: 2,
  height: 0.05,
  depth: 1,
  color: 0x8B4513
});

// Table legs (4 cylinders)
const legPositions = [
  [4.2, 0.375, 4.4],
  [5.8, 0.375, 4.4],
  [4.2, 0.375, 5.6],
  [5.8, 0.375, 5.6]
];

legPositions.forEach(([x, y, z]) => {
  openPlans.cylinder({
    center: new Vector3(x, y, z),
    radius: 0.05,
    height: 0.75,
    segments: 16,
    color: 0x654321
  });
});

Creating Furniture Layout

// Bed
const bed = openPlans.cuboid({
  center: new Vector3(2, 0.4, 2),
  width: 2,
  height: 0.4,
  depth: 1.8,
  color: 0x4A4A4A
});

// Wardrobe
const wardrobe = openPlans.cuboid({
  center: new Vector3(1, 1.2, 0.3),
  width: 2,
  height: 2.4,
  depth: 0.6,
  color: 0x8B7355
});

// Desk
const desk = openPlans.cuboid({
  center: new Vector3(4, 0.75, 1),
  width: 1.5,
  height: 0.05,
  depth: 0.7,
  color: 0xD2691E
});

Combining Shapes with Primitives

3D shapes work seamlessly with 2D primitives:
// Create room outline (2D)
const roomOutline = openPlans.rectangle({
  center: [5, 0, 5],
  width: 10,
  breadth: 8,
  color: 0x000000
});

// Add walls (3D)
const frontWall = openPlans.cuboid({
  center: new Vector3(5, 1.5, 1),
  width: 10,
  height: 3,
  depth: 0.2,
  color: 0xEEEEEE
});

const backWall = openPlans.cuboid({
  center: new Vector3(5, 1.5, 9),
  width: 10,
  height: 3,
  depth: 0.2,
  color: 0xEEEEEE
});

const leftWall = openPlans.cuboid({
  center: new Vector3(0, 1.5, 5),
  width: 0.2,
  height: 3,
  depth: 8,
  color: 0xEEEEEE
});

const rightWall = openPlans.cuboid({
  center: new Vector3(10, 1.5, 5),
  width: 0.2,
  height: 3,
  depth: 8,
  color: 0xEEEEEE
});

Managing 3D Shapes

Getting All Shapes

const allCuboids = openPlans.getEntitiesByType('CuboidShape');
const allCylinders = openPlans.getEntitiesByType('CylinderShape');

const totalShapes = allCuboids.length + allCylinders.length;
console.log(`Total 3D shapes: ${totalShapes}`);

Disposing Shapes

// Dispose a specific shape
const shapeId = cuboid.ogid;
openPlans.disposeElement(shapeId);

// Dispose all cuboids
allCuboids.forEach(cuboid => {
  openPlans.disposeElement(cuboid.ogid);
});

Complete Example: 3D Room Model

import { OpenPlans, Vector3 } from 'openplans';

async function create3DRoom() {
  const container = document.getElementById('app');
  const openPlans = new OpenPlans(container);
  await openPlans.setupOpenGeometry();
  
  const roomWidth = 6;
  const roomDepth = 5;
  const roomHeight = 3;
  const wallThickness = 0.2;
  
  // Floor
  const floor = openPlans.cuboid({
    center: new Vector3(roomWidth/2, -0.1, roomDepth/2),
    width: roomWidth,
    height: 0.2,
    depth: roomDepth,
    color: 0xCCCCCC
  });
  
  // Walls
  const walls = [
    // Front wall
    openPlans.cuboid({
      center: new Vector3(roomWidth/2, roomHeight/2, 0),
      width: roomWidth,
      height: roomHeight,
      depth: wallThickness,
      color: 0xF5F5F5
    }),
    // Back wall
    openPlans.cuboid({
      center: new Vector3(roomWidth/2, roomHeight/2, roomDepth),
      width: roomWidth,
      height: roomHeight,
      depth: wallThickness,
      color: 0xF5F5F5
    }),
    // Left wall
    openPlans.cuboid({
      center: new Vector3(0, roomHeight/2, roomDepth/2),
      width: wallThickness,
      height: roomHeight,
      depth: roomDepth,
      color: 0xF5F5F5
    }),
    // Right wall
    openPlans.cuboid({
      center: new Vector3(roomWidth, roomHeight/2, roomDepth/2),
      width: wallThickness,
      height: roomHeight,
      depth: roomDepth,
      color: 0xF5F5F5
    })
  ];
  
  // Ceiling
  const ceiling = openPlans.cuboid({
    center: new Vector3(roomWidth/2, roomHeight, roomDepth/2),
    width: roomWidth,
    height: 0.2,
    depth: roomDepth,
    color: 0xFFFFFF
  });
  
  // Column in corner
  const column = openPlans.cylinder({
    center: new Vector3(1, roomHeight/2, 1),
    radius: 0.2,
    height: roomHeight,
    segments: 32,
    color: 0x888888
  });
  
  console.log('3D room created successfully');
}

create3DRoom();

Next Steps

Last modified on March 7, 2026