123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132 |
- /*
- * Revolver.js
- *
- * @author realor
- */
- import { ObjectBuilder } from './ObjectBuilder.js'
- import { SweptSolidBuilder } from './SweptSolidBuilder.js'
- import { Solid } from '../core/Solid.js'
- import { Profile } from '../core/Profile.js'
- import { Cord } from '../core/Cord.js'
- import { SolidGeometry } from '../core/SolidGeometry.js'
- import { ProfileGeometry } from '../core/ProfileGeometry.js'
- import * as THREE from '../lib/three.module.js'
- class Revolver extends SweptSolidBuilder {
- angle = 90 // degrees
- location = new THREE.Vector3()
- axis = new THREE.Vector3(0, 1, 0)
- segments = 32 // segments per turn (360 degress)
- smoothAngle = 5 // degrees
- optimize = true // optimize geometry
- constructor(angle, location, axis, segments) {
- super()
- if (typeof angle === 'number') {
- this.angle = angle
- }
- if (location instanceof THREE.Vector3) {
- this.location.copy(location)
- }
- if (axis instanceof THREE.Vector3) {
- this.axis.copy(axis)
- }
- if (typeof segments === 'number') {
- if (segments > 2) {
- this.segments = segments
- }
- }
- }
- performBuild(solid) {
- let profile = this.findClosedProfile(solid)
- if (profile === undefined) return true
- let [outerRing, innerRings, stepVertexCount] = this.prepareRings(profile)
- const yAxis = new THREE.Vector3()
- yAxis.copy(this.axis).normalize()
- const xAxis = new THREE.Vector3(yAxis.y, -yAxis.x, 0)
- const zAxis = new THREE.Vector3()
- zAxis.crossVectors(xAxis, yAxis)
- const baseMatrix = new THREE.Matrix4()
- baseMatrix.makeBasis(xAxis, yAxis, zAxis)
- baseMatrix.setPosition(this.location)
- const baseMatrixInverse = new THREE.Matrix4()
- baseMatrixInverse.copy(baseMatrix).invert()
- const geometry = new SolidGeometry()
- let angle = Math.abs(this.angle)
- if (angle > 360) angle = 360
- let reverse = Math.sign(this.angle) === -1
- let steps = Math.ceil((this.segments * angle) / 360)
- const angleRad = THREE.MathUtils.degToRad(angle)
- let stepAngleRad = steps > 0 ? angleRad / steps : 0
- if (reverse) {
- stepAngleRad *= -1
- }
- let offset1 = -1
- let offset2 = 0
- const matrix = new THREE.Matrix4()
- const rotationMatrix = new THREE.Matrix4()
- for (let i = 0; i <= steps; i++) {
- rotationMatrix.makeRotationY(stepAngleRad * i)
- matrix.copy(baseMatrix)
- matrix.multiply(rotationMatrix)
- matrix.multiply(baseMatrixInverse)
- matrix.multiply(profile.matrix)
- if (i === steps && angle === 360) {
- offset2 = 0
- } else {
- this.addStepVertices(outerRing, innerRings, matrix, geometry)
- }
- // add faces
- if (i === 0 && angle < 360 && steps > 0) {
- // first face
- this.addProfileFace(0, outerRing, innerRings, !reverse, geometry)
- } else if (i === steps && angle < 360) {
- // last face
- this.addProfileFace(offset2, outerRing, innerRings, reverse, geometry)
- }
- if (offset1 >= 0 && steps > 0) {
- this.addLateralFaces(offset1, offset2, outerRing, innerRings, reverse, geometry)
- }
- offset1 = offset2
- offset2 += stepVertexCount
- }
- geometry.isManifold = steps > 0
- geometry.smoothAngle = this.smoothAngle
- solid.updateGeometry(geometry, this.optimize)
- return true
- }
- copy(source) {
- this.angle = source.angle
- this.location.copy(source.location)
- this.axis.copy(source.axis)
- this.segments = source.segments
- this.smoothAngle = source.smothAngle // degrees
- this.optimize = source.optimize
- this.minPointDistance = source.minPointDistance
- return this
- }
- }
- ObjectBuilder.addClass(Revolver)
- export { Revolver }
|