Skip to main content
Documentation

Sculpt

Draw and edit points, lines, polygons, rectangles, and other 3D objects in a Five SDK scene.

import { Five } from '@realsee/five'
const five: Five = {} as any
// - five
import { Sculpt } from '@realsee/dnalogel'
const sculpt = new Sculpt(five)
// - sculpt
const item = sculpt.getItemById('1')!
// - item

Overview

Sculpt (/ skʌlpt / vt. to carve; n. sculpture) is a 3D editor built on top of @realsee/five, used to draw and edit 3D objects within a Five SDK scene.

Demo

Open the official Sculpt demo.

Quick Start

Initialization

Initialize via Five SDK plugins:

import { SculptPlugin } from '@realsee/dnalogel'
import { Five } from '@realsee/five'
import type { FivePlugin } from '@realsee/five'

const fivePlugins: [FivePlugin<any, any>, string, any][] = [
  [SculptPlugin, 'sculpt', {}]
]

// Load the Five plugin
const five = new Five({
  plugins: fivePlugins
})

You can also initialize it yourself:

// @include: main-five

// ---cut---
import { Sculpt } from '@realsee/dnalogel'

const sculpt = new Sculpt(five) // five is a Five instance; theme is optional

Loading Data

There are two ways to add objects to a sculpt scene. The first is to load existing data via the sculpt.load(data) method. List item data structure: data

// @include: main

// ---cut---
const data = {
  items: [
    {
      id: '1',
      type: 'Point',
      point: [0, 0, 0]
    },
    {
      id: '2',
      type: 'Polyline',
      points: [[0, 0, 0], [1, 1, 1]]
    }
  ]
}

// Draw a point and a line in the scene
sculpt.load(data)

Creating Objects

The other way to add objects to a sculpt scene is to create them via the sculpt.createXXXX() methods.

Draw a Box

  // @include: main

  // ---cut---
  sculpt.createBox()

Draw a red Box with a green border

  // @include: main

  // ---cut---
  sculpt.createBox({ color: 0xff0000, opacity: 0.8, lineColor: 0x00ff00, lineWidth: 2 })

Draw a red line segment

  // @include: main

  // ---cut---
  sculpt.createLine({ lineColor: 0xff0000 })

Draw a line segment with a distance label

  // @include: main

  // ---cut---
  sculpt.createLine({ lengthEnable: true })

Draw a line segment with a tip

  // @include: main

  // ---cut---
  sculpt.createLine({ tip: 'Line segment' })

Draw a line segment locked to the horizontal plane

  // @include: main

  // ---cut---
  sculpt.createLine({ limit: 'xoz' })

Draw a rectangle locked to a vertical plane, drawn by its diagonal

  // @include: main

  // ---cut---
  sculpt.createRectangle({ limit: 'y', drawMethod: 'diagonal' })

More flexible drawing and editing

  // @include: main

  // ---cut---
  import { Util } from '@realsee/dnalogel'

  const { PointSelector } = Util
  const { BoxMesh, BoxMeshEditor, createBox } = Util.sculpt

  // Create a boxMesh
  const boxMesh = new BoxMesh({ lineColor: 0xff0000 })
  five.scene.add(boxMesh)

  // Initialize the editor as needed
  const editor = new BoxMeshEditor(boxMesh)

  // Create a selector
  const pointSelector = new PointSelector(five)

  createBox(boxMesh, pointSelector).then(() => {
    console.log('Drawing complete')

    // Enable editing as needed
    editor.enable()
  })

Enabling Editing

Editing is enabled by default. You can disable the default behavior by passing an argument when loading data:

  // @include: main

  const data = {
    items: [
      {
        id: '1',
        type: 'Point',
        point: [0, 0, 0]
      },
      {
        id: '2',
        type: 'Polyline',
        points: [[0, 0, 0], [1, 1, 1]]
      }
    ]
  }

  // ---cut---
  sculpt.load(data, { defaultAction: false })

Click to start editing

  // @include: main

  // ---cut---
  sculpt.on('click', (e, item) => {
    // Select on click (with a highlight effect)
    item.select({ only: true })

    // Enable editing after the click
    item.editor.enable()

    // Triggered when the object is moved/rotated/scaled
    item.editor.hooks.on('objectUpdate', () => {
      console.log('new Data: ', item.data)
    })
  })

Click to show the delete button

  // @include: main

  // ---cut---
  sculpt.on('click', (e, item) => {
    const point = e instanceof TouchEvent ? e.touches[0] : e
    if (!point) return
    const { clientX: x, clientY: y } = point
    item.showDeleteButton(x, y)
  })

Sculpt API

Glossary

Item

The instance of an object. Every object in sculpt is an Item. API

Currently supported Item kinds: ItemType

Theme

At initialization you can set the default style for each type of object.

// @include: main-five

// ---cut---
import { Sculpt } from '@realsee/dnalogel'

/**
 * - color: fill color
 * - opacity: opacity
 * - lineColor: border line color
 * - lineWidth: line width
 * - lineOpacity: border line opacity
 * - occlusionVisibility: whether to render occluded portions in a semi-transparent way
 * - occlusionMode: occlusion mode
 */
const theme = {
  point: { color: 0xffffff },
  line: { lineColor: 0xffffff, lineWidth: 1 },
  polyline: { lineColor: 0x0000ff, lineWidth: 2 },
  polygon: { color: 0xffffff, lineColor: 0x000000, lineWidth: 2, lineOpacity: 0.8 },
  prism: { color: 0xffffff, lineColor: 0x000000, lineWidth: 2, lineOpacity: 1 },
  rectangle: { color: 0xffffff, lineColor: 0x000000, opacity: 0.5 },
  circle: { color: 0xffffff, lineColor: 0x000000, occlusionVisibility: false },
  cylinder: { color: 0xffffff, lineColor: 0x000000, occlusionMode: 'translucence' },
  box: { color: 0xffffff, lineColor: 0x000000 },
} as const

const sculpt = new Sculpt(five, theme)

sculpt.data

// @include: main

// ---cut---
const data = sculpt.data

Gets the full Item data for the current scene.

sculpt.items

Return value: Item[]

Gets all Item instances in the current scene.

sculpt.load(data)

Loads data and renders it into the scene.

sculpt.createXXXX()

Starts drawing an object on screen. Drawing is completed through mouse clicks, dragging, keyboard shortcuts (esc), and similar interactions.

Supported functions:

// @include: main

// ---cut---
sculpt.createPoint() // draw a point
sculpt.createLine() // draw a line segment
sculpt.createPolyline() // draw a polyline
sculpt.createPolygon() // draw a polygon
sculpt.createRectangle() // draw a rectangle
sculpt.createCircle() // draw a circle
sculpt.createPrism() // draw a prism
sculpt.createBox() // draw a Box/cuboid
sculpt.createCylinder() // draw a cylinder

sculpt.getItemById(id)

Gets an Item instance by id.

// @include: main-sculpt
// ---cut---
const item = sculpt.getItemById('1')

sculpt.clear()

Clears all objects from the scene.

// @include: main
// ---cut---
sculpt.clear()

Item API

item.type

Return value: ItemType

Returns the type of the current Item.

item.data

Returns the data of the current Item.

item.setData()

Sets the data of the current Item. Parameter data structure: data

item.create()

// @include: main
// ---cut---
item.create()

Starts drawing the Item through mouse, keyboard, and other interactions.

item.stopCreating()

// @include: main
// ---cut---
item.stopCreating()

Exits creation of the current Item, equivalent to the esc shortcut. If the current Item has not finished drawing, it will be deleted.

item.delete()

// @include: main
// ---cut---
item.delete()

Deletes the current Item.

item.on(event)

// @include: main
// ---cut---
// @noErrors
item.on('')
//       ^|







import type * as THREE from 'three'

type EventName = keyof FiveDomEventMap

type PreventFiveEvent = boolean

// ---cut---

interface FiveDomEvent {
  type: EventName
  target: THREE.Object3D
  origDomEvent?: Event
  raycaster: THREE.Raycaster
  intersects?: THREE.Intersection[]
  stopPropagation: () => void
}

interface FiveDomEventMap {
  /**
   * @description click event
   * @return {PreventFiveEvent} return false to allow Five's tap event to fire; default: true
   */
  click: (event: FiveDomEvent) => PreventFiveEvent | void

  /**
   * @description double-click event
   */
  dblclick: (event: FiveDomEvent) => void

  /**
   * @description mouse down event
   */
  mousedown: (event: FiveDomEvent) => void

  /**
   * @description mouse up event
   */
  mouseup: (event: FiveDomEvent) => void

  /**
   * @description mouse enter event
   */
  hover: (event: FiveDomEvent) => void

  /**
   * @description mouse leave event
   */
  unHover: (event: FiveDomEvent) => void

  /**
   * @description: drag start
   */
  dragstart: (event: FiveDomEvent) => void

  /**
   * @description: dragging
   */
  drag: (event: FiveDomEvent) => void

  /**
   * @description: drag end
   */
  dragend: (event: FiveDomEvent) => void
}

Reference

ItemType

type ItemType =
  | 'Point' // point
  | 'Line' // line segment
  | 'Polyline' // line segment / polyline
  | 'Polygon' // polygon
  | 'Rectangle' // rectangle
  | 'Circle' // circle
  | 'Prism' // prism
  | 'Box' // Box/cuboid
  | 'Cylinder' // cylinder

data

Hover over the corresponding data to view its type.

// import type { SculptData } from "@realsee/dnalogel"

// ---cut---
import type { SculptData } from "@realsee/dnalogel"

/**
 * point: coordinates of a point in 3D space
 */
type PointData = SculptData.PointData
/**
 * points: the set of point coordinates of the polyline
 */
type PolylineData = SculptData.PolylineData
/**
 * points: the set of vertex coordinates of the polygon
 */
type PolygonData = SculptData.PolygonData
/**
 * points: the set of the four vertex coordinates of the rectangle
 */
type RectangleData = SculptData.RectangleData
/**
 * center: coordinates of the circle's center
 * normal: the circle's normal vector
 * radius: the circle's radius
 */
type CircleData = SculptData.CircleData
/**
 * points: the set of bottom-face vertex coordinates of the prism
 * heightPoint: coordinates of the top-face point corresponding to the first point of the bottom face
 */
type PrismData = SculptData.PrismData
/**
 * points: the set of bottom-face vertex coordinates of the box
 * heightPoint: coordinates of the top-face point corresponding to the first point of the bottom face
 */
type BoxData = SculptData.BoxData
/**
 * bottomCenter: coordinates of the cylinder's bottom-face center
 * topCenter: coordinates of the cylinder's top-face center
 * radius: the cylinder's radius
 */
type CylinderData = SculptData.CylinderData