@polygonjs/polygonjs
Version:
node-based WebGL 3D engine https://polygonjs.com
153 lines (138 loc) • 5.13 kB
text/typescript
import {BaseSopOperation} from './_Base';
import {CoreGroup} from '../../../core/geometry/Group';
import {IcosahedronGeometry, BufferGeometry, Vector2, Vector3, Box3} from 'three';
import {InputCloneMode} from '../../../engine/poly/InputCloneMode';
import {isBooleanTrue} from '../../../core/BooleanValue';
import {DefaultOperationParams} from '../../../core/operations/_Base';
import {ObjectType} from '../../../core/geometry/Constant';
import {SphereBuilder} from '../../../core/geometry/builders/SphereBuilder';
const tmpBox = new Box3();
const tmpSize = new Vector3();
const tmpCenter = new Vector3();
interface SphereSopParams extends DefaultOperationParams {
type: number;
radius: number;
resolution: Vector2;
open: boolean;
phiStart: number;
phiLength: number;
thetaStart: number;
thetaLength: number;
detail: number;
center: Vector3;
asLines: boolean;
}
enum SphereType {
DEFAULT = 'default',
ISOCAHEDRON = 'isocahedron',
}
type SphereTypes = {[key in SphereType]: number};
export const SPHERE_TYPE: SphereTypes = {
default: 0,
isocahedron: 1,
};
export const SPHERE_TYPES: Array<SphereType> = [SphereType.DEFAULT, SphereType.ISOCAHEDRON];
export class SphereSopOperation extends BaseSopOperation {
static override readonly DEFAULT_PARAMS: SphereSopParams = {
type: SPHERE_TYPE.default,
radius: 1,
resolution: new Vector2(30, 30),
open: false,
phiStart: 0,
phiLength: Math.PI * 2,
thetaStart: 0,
thetaLength: Math.PI,
detail: 1,
center: new Vector3(0, 0, 0),
asLines: false,
};
static override readonly INPUT_CLONED_STATE = InputCloneMode.NEVER;
static override type(): Readonly<'sphere'> {
return 'sphere';
}
override cook(inputCoreGroups: CoreGroup[], params: SphereSopParams) {
const coreGroup = inputCoreGroups[0];
const object = coreGroup ? this._cookWithInput(coreGroup, params) : this._cookWithoutInput(params);
if (this._node) {
object.name = this._node.name();
}
return this.createCoreGroupFromObjects([object]);
}
private _cookWithoutInput(params: SphereSopParams) {
const geometry = this._createRequiredGeometry(params);
geometry.translate(params.center.x, params.center.y, params.center.z);
const object = this._createSphereObject(geometry, params);
return object;
}
private _cookWithInput(coreGroup: CoreGroup, params: SphereSopParams) {
coreGroup.boundingBox(tmpBox);
tmpBox.getSize(tmpSize);
tmpBox.getCenter(tmpCenter);
const geometry = this._createRequiredGeometry(params);
geometry.scale(tmpSize.x, tmpSize.y, tmpSize.z);
geometry.translate(params.center.x, params.center.y, params.center.z);
geometry.translate(tmpCenter.x, tmpCenter.y, tmpCenter.z);
const object = this._createSphereObject(geometry, params);
return object;
}
private _createSphereObject(geometry: BufferGeometry, params: SphereSopParams) {
return BaseSopOperation.createObject(geometry, params.asLines ? ObjectType.LINE_SEGMENTS : ObjectType.MESH);
}
private _createRequiredGeometry(params: SphereSopParams) {
if (params.type == SPHERE_TYPE.default) {
return this._createDefaultSphere(params);
} else {
return this._createDefaultIsocahedron(params);
}
}
private _createDefaultSphere(params: SphereSopParams) {
const geometry = isBooleanTrue(params.open)
? SphereBuilder.create({
radius: params.radius,
widthSegments: params.resolution.x,
heightSegments: params.resolution.y,
phiStart: params.phiStart,
phiLength: params.phiLength,
thetaStart: params.thetaStart,
thetaLength: params.thetaLength,
asLines: params.asLines,
open: true,
})
: SphereBuilder.create({
radius: params.radius,
widthSegments: params.resolution.x,
heightSegments: params.resolution.y,
asLines: params.asLines,
open: false,
});
// if (isBooleanTrue(params.asLines)) {
// // const widthSegments = Math.max( 3, Math.floor( params.resolution.x ) );
// // const heightSegments = Math.max( 2, Math.floor( params.resolution.y ) );
// const newIndices: number[] = [];
// // for ( let iy = 0; iy < heightSegments; iy ++ ) {
// // for ( let ix = 0; ix < widthSegments; ix ++ ) {
// // const a = grid[ iy ][ ix + 1 ];
// // const b = grid[ iy ][ ix ];
// // const c = grid[ iy + 1 ][ ix ];
// // const d = grid[ iy + 1 ][ ix + 1 ];
// // if ( iy !== 0 || thetaStart > 0 ) indices.push( a, b, d );
// // if ( iy !== heightSegments - 1 || thetaEnd < Math.PI ) indices.push( b, c, d );
// // }
// // }
// // geometry.setIndex(indices);
// const currentIndices: number[] = geometry.getIndex()!.array as number[];
// const facesCount = currentIndices.length / 3;
// for (let faceIndex = 0; faceIndex < facesCount; faceIndex += 2) {
// const a = currentIndices[faceIndex];
// const b = currentIndices[faceIndex + 1];
// // const c = currentIndices[faceIndex+2]
// newIndices.push(a, b);
// // newIndices.push(a,c)
// }
// }
return geometry;
}
private _createDefaultIsocahedron(params: SphereSopParams) {
return new IcosahedronGeometry(params.radius, params.detail);
}
}