@polygonjs/polygonjs
Version:
node-based WebGL 3D engine https://polygonjs.com
199 lines (185 loc) • 6.76 kB
text/typescript
/**
* Create a physics world
*
*
*/
import {Group, Object3D} from 'three';
import {
initCorePhysicsWorld,
physicsWorldNodeIdFromObject,
PHYSICS_GRAVITY_DEFAULT,
} from './../../../core/physics/PhysicsWorld';
import {TypedActorSopNode} from './_BaseActor';
import {CoreGroup} from '../../../core/geometry/Group';
import {NodeParamsConfig, ParamConfig} from '../utils/params/ParamsConfig';
import {NodeContext} from '../../poly/NodeContext';
import {InputCloneMode} from '../../poly/InputCloneMode';
import {createOrFindPhysicsWorld} from '../../../core/physics/PhysicsWorld';
import {updatePhysicsDebugObject} from '../../../core/physics/PhysicsDebug';
import {SopType} from '../../poly/registers/nodes/types/Sop';
import {PolyScene} from '../../scene/PolyScene';
import {isFunction} from '../../../core/Type';
import {BaseNodeType} from '../_Base';
import {Poly} from '../../Poly';
import {ThreejsCoreObject} from '../../../core/geometry/modules/three/ThreejsCoreObject';
import {PhysicsIdAttribute} from '../../../core/physics/PhysicsAttribute';
import {CorePhysics} from '../../../core/physics/CorePhysics';
import {setJointDataListForWorldObject} from '../../../core/physics/PhysicsJoint';
class PhysicsWorldSopParamsConfig extends NodeParamsConfig {
/** @param gravity */
gravity = ParamConfig.VECTOR3(PHYSICS_GRAVITY_DEFAULT);
/** @param display debug information */
// debug = ParamConfig.BOOLEAN(0);
/** @param actor node */
// node = ParamConfig.NODE_PATH('', {
// visibleIf: {useThisNode: 0},
// // nodeSelection: {
// // // context: NodeContext.ACTOR,
// // },
// dependentOnFoundNode: false,
// });
}
const ParamsConfig = new PhysicsWorldSopParamsConfig();
export class PhysicsWorldSopNode extends TypedActorSopNode<PhysicsWorldSopParamsConfig> {
override readonly paramsConfig = ParamsConfig;
static override type(): SopType.PHYSICS_WORLD {
return SopType.PHYSICS_WORLD;
}
protected override initializeNode() {
this.io.inputs.setCount(1);
// set to always clone, so that we reset the world
// by simply setting this node to dirty
this.io.inputs.initInputsClonedState(InputCloneMode.ALWAYS);
}
override async cook(inputCoreGroups: CoreGroup[]) {
this.compilationController.compileIfRequired();
await CorePhysics();
const coreGroup = inputCoreGroups[0];
const worldObject = new Group();
worldObject.name = this.name();
worldObject.matrixAutoUpdate = false;
Poly.onObjectsAddRemoveHooks.assignOnAddHookHandler(worldObject, this);
ThreejsCoreObject.addAttribute(worldObject, PhysicsIdAttribute.WORLD, this.graphNodeId());
const inputObjects = coreGroup.threejsObjects();
for (const inputObject of inputObjects) {
worldObject.add(inputObject);
}
setJointDataListForWorldObject(this.scene(), worldObject);
// const {world, PhysicsLib} = await createOrFindPhysicsWorld(this, worldObject, this.pv.gravity);
// this._PhysicsLib = PhysicsLib;
// initCorePhysicsWorld(this._PhysicsLib, worldObject, this.scene());
// if (actorNode) {
// }
// const objects: Object3D[] = [worldObject];
// if (isBooleanTrue(this.pv.debug)) {
// // const pair = createOrFindPhysicsDebugObject(this, world);
// // updatePhysicsDebugObject(pair);
// const debugObject = physicsCreateDebugObject();
// CoreObject.addAttribute(debugObject, PhysicsIdAttribute.DEBUG, this.graphNodeId());
// debugObject.name = `${this.name()}_Debug`;
// objects.push(debugObject);
// }
const actorNode = this._findActorNode();
// for (let object of objects) {
// do not assign actor node to the debug object
this.scene().actorsManager.assignActorBuilder(worldObject, actorNode);
// }
this.setObject(worldObject);
}
public override updateObjectOnAdd(object: Object3D) {
// if (!this._PhysicsLib) {
// return;
// }
const worldNodeId = ThreejsCoreObject.attribValue(object, PhysicsIdAttribute.WORLD);
if (worldNodeId != null) {
if (worldNodeId != this.graphNodeId()) {
return;
}
const worldObject = object;
createOrFindPhysicsWorld(this, worldObject, this.pv.gravity).then(({world, PhysicsLib}) => {
initCorePhysicsWorld(PhysicsLib, worldObject, this.scene());
// once world is create, try and find a sibbling that matches the debug object,
// then updated it accordingly
const sibblings = worldObject.parent?.children.filter((sibbling) => sibbling.uuid != worldObject.uuid);
if (!sibblings) {
return;
}
const debugObject = sibblings.find(
(sibbling) => ThreejsCoreObject.attribValue(sibbling, PhysicsIdAttribute.DEBUG_WORLD) == worldNodeId //this.graphNodeId()
);
if (debugObject) {
updatePhysicsDebugObject(debugObject);
}
// if (isBooleanTrue(this.pv.debug)) {
// const pair = createOrFindPhysicsDebugObject(this, world);
// updatePhysicsDebugObject(pair);
// objects.push(pair.object);
// }
// for (let object of objects) {
// this.scene().actorsManager.assignActorBuilder(object, actorNode);
// }
});
// initCorePhysicsWorld(this._PhysicsLib, object, this.scene());
}
}
private _findActorNode() {
// if (isBooleanTrue(this.pv.useThisNode)) {
return this;
// } else {
// return this.pv.node.node() as ActorBuilderNode | undefined;
// }
}
//
// CHILDREN
//
// protected override _childrenControllerContext = NodeContext.JS;
// override createNode<S extends keyof JsNodeChildrenMap>(
// node_class: S,
// options?: NodeCreateOptions
// ): JsNodeChildrenMap[S];
// override createNode<K extends valueof<JsNodeChildrenMap>>(
// node_class: Constructor<K>,
// options?: NodeCreateOptions
// ): K;
// override createNode<K extends valueof<JsNodeChildrenMap>>(
// node_class: Constructor<K>,
// options?: NodeCreateOptions
// ): K {
// return super.createNode(node_class, options) as K;
// }
// override children() {
// return super.children() as BaseJsNodeType[];
// }
// override nodesByType<K extends keyof JsNodeChildrenMap>(type: K): JsNodeChildrenMap[K][] {
// return super.nodesByType(type) as JsNodeChildrenMap[K][];
// }
// override childrenAllowed() {
// return true;
// }
}
export function getPhysicsWorldNodeFromWorldObject(
worldObject: Object3D,
scene: PolyScene
): PhysicsWorldSopNode | undefined {
const nodeId = physicsWorldNodeIdFromObject(worldObject);
if (nodeId == null) {
return;
}
const graphNode = scene.graph.nodeFromId(nodeId);
if (!graphNode) {
return;
}
const node: BaseNodeType | null = isFunction((graphNode as BaseNodeType).context)
? (graphNode as BaseNodeType)
: null;
if (!node) {
return;
}
if (node.context() != NodeContext.SOP) {
return;
}
if (node.type() != SopType.PHYSICS_WORLD) {
return;
}
return node as PhysicsWorldSopNode;
}