mlightcad
Version:
A highly customizable standalone view cube addon for three.js
146 lines (124 loc) • 3.85 kB
text/typescript
import * as THREE from 'three'
import { createTextSprite } from './viewCubeData'
import { FixedPosGizmo, ObjectPosition } from './fixedPosGizmo'
/**
* Options to customize axes
*/
export interface AxesOptions {
/**
* Position of axes
*/
pos?: ObjectPosition
/**
* Size of area ocupied by view cube. Because width and height of this area is same, it is single value.
* The real size of view cube will be calculated automatically considering rotation.
*/
size?: number
/**
* Flag to show z-axis
*/
hasZAxis?: boolean
}
/**
* Default axes option values
*/
export const DEFAULT_AXES_OPTIONS: AxesOptions = {
pos: ObjectPosition.LEFT_BOTTOM,
size: 100,
hasZAxis: true
}
/**
* An axis gizmo to visualize the axes in a simple way.
* The X axis is red, the Y axis is green, and the Z axis is blue by default
*/
export class AxesGizmo extends FixedPosGizmo {
private axes: THREE.LineSegments
private xText: THREE.Sprite
private yText: THREE.Sprite
private zText?: THREE.Sprite
private hasZAxis: boolean
constructor(
camera: THREE.PerspectiveCamera | THREE.OrthographicCamera,
renderer: THREE.WebGLRenderer,
options: AxesOptions
) {
const mergedOptions: AxesOptions = {
...DEFAULT_AXES_OPTIONS,
...options
}
super(camera, renderer, mergedOptions.size, options.pos)
this.hasZAxis = mergedOptions.hasZAxis!
const vertices = [0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 2, 0]
const colors = [1, 0, 0, 1, 0.6, 0, 0, 1, 0, 0.6, 1, 0]
if (this.hasZAxis) {
vertices.push(0, 0, 0, 0, 0, 2)
colors.push(0, 0, 1, 0, 0.6, 1)
}
const geometry = new THREE.BufferGeometry()
geometry.setAttribute(
'position',
new THREE.Float32BufferAttribute(vertices, 3)
)
geometry.setAttribute('color', new THREE.Float32BufferAttribute(colors, 3))
const material = new THREE.LineBasicMaterial({
vertexColors: true,
toneMapped: false
})
this.axes = new THREE.LineSegments(geometry, material)
this.axes.position.set(-1, -1, -1)
this.add(this.axes)
this.xText = createTextSprite('X')
this.xText.position.set(1.5, -1, -1)
this.add(this.xText)
this.yText = createTextSprite('Y')
this.yText.position.set(-1, 1.5, -1)
this.add(this.yText)
if (this.hasZAxis) {
this.zText = createTextSprite('Z')
this.zText.position.set(-1, -1, 1.5)
this.add(this.zText)
}
}
/**
* Set color of x-axis and y-axis
* @param xAxisColor color of x-axis
* @param yAxisColor color of y-axis
*/
setLineColors(xAxisColor: THREE.Color, yAxisColor: THREE.Color) {
const color = new THREE.Color()
const array = this.axes.geometry.attributes.color.array
color.set(xAxisColor)
color.toArray(array, 0)
color.toArray(array, 3)
color.set(yAxisColor)
color.toArray(array, 6)
color.toArray(array, 9)
this.axes.geometry.attributes.color.needsUpdate = true
return this
}
/**
* Set text color
* @param color text color
*/
setTextColor(color: THREE.Color) {
this.xText.material.color = color
this.yText.material.color = color
}
/**
* Free the GPU-related resources allocated by this instance. Call this method whenever this instance
* is no longer used in your app.
*/
dispose() {
this.axes.geometry.dispose()
const material = this.axes.material as THREE.LineBasicMaterial
material.dispose()
this.xText.geometry.dispose()
this.xText.material.dispose()
this.yText.geometry.dispose()
this.yText.material.dispose()
if (this.hasZAxis) {
this.zText?.geometry.dispose()
this.zText?.material.dispose()
}
}
}