playcanvas
Version:
Open-source WebGL/WebGPU 3D engine for the web
169 lines (168 loc) • 5.73 kB
JavaScript
var __defProp = Object.defineProperty;
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
import { RENDERSTYLE_WIREFRAME } from "./constants.js";
import { MeshInstance } from "./mesh-instance.js";
import { MorphInstance } from "./morph-instance.js";
import { SkinInstance } from "./skin-instance.js";
class Model {
/**
* Creates a new model.
*
* @example
* // Create a new model
* const model = new pc.Model();
*/
constructor() {
/**
* The root node of the model's graph node hierarchy.
*
* @type {GraphNode|null}
*/
__publicField(this, "graph", null);
/**
* An array of MeshInstances contained in this model.
*
* @type {MeshInstance[]}
*/
__publicField(this, "meshInstances", []);
/**
* An array of SkinInstances contained in this model.
*
* @type {SkinInstance[]}
*/
__publicField(this, "skinInstances", []);
/**
* An array of MorphInstances contained in this model.
*
* @type {MorphInstance[]}
*/
__publicField(this, "morphInstances", []);
this.cameras = [];
this.lights = [];
this._shadersVersion = 0;
this._immutable = false;
}
getGraph() {
return this.graph;
}
setGraph(graph) {
this.graph = graph;
}
getCameras() {
return this.cameras;
}
setCameras(cameras) {
this.cameras = cameras;
}
getLights() {
return this.lights;
}
setLights(lights) {
this.lights = lights;
}
getMaterials() {
const materials = [];
for (let i = 0; i < this.meshInstances.length; i++) {
const meshInstance = this.meshInstances[i];
if (materials.indexOf(meshInstance.material) === -1) {
materials.push(meshInstance.material);
}
}
return materials;
}
/**
* Clones a model. The returned model has a newly created hierarchy and mesh instances, but
* meshes are shared between the clone and the specified model.
*
* @returns {Model} A clone of the specified model.
* @example
* const clonedModel = model.clone();
*/
clone() {
const srcNodes = [];
const cloneNodes = [];
const _duplicate = function(node) {
const newNode = node.clone();
srcNodes.push(node);
cloneNodes.push(newNode);
for (let idx = 0; idx < node._children.length; idx++) {
newNode.addChild(_duplicate(node._children[idx]));
}
return newNode;
};
const cloneGraph = _duplicate(this.graph);
const cloneMeshInstances = [];
const cloneSkinInstances = [];
const cloneMorphInstances = [];
for (let i = 0; i < this.skinInstances.length; i++) {
const skin = this.skinInstances[i].skin;
const cloneSkinInstance = new SkinInstance(skin);
const bones = [];
for (let j = 0; j < skin.boneNames.length; j++) {
const boneName = skin.boneNames[j];
const bone = cloneGraph.findByName(boneName);
bones.push(bone);
}
cloneSkinInstance.bones = bones;
cloneSkinInstances.push(cloneSkinInstance);
}
for (let i = 0; i < this.morphInstances.length; i++) {
const morph = this.morphInstances[i].morph;
const cloneMorphInstance = new MorphInstance(morph);
cloneMorphInstances.push(cloneMorphInstance);
}
for (let i = 0; i < this.meshInstances.length; i++) {
const meshInstance = this.meshInstances[i];
const nodeIndex = srcNodes.indexOf(meshInstance.node);
const cloneMeshInstance = new MeshInstance(meshInstance.mesh, meshInstance.material, cloneNodes[nodeIndex]);
if (meshInstance.skinInstance) {
const skinInstanceIndex = this.skinInstances.indexOf(meshInstance.skinInstance);
cloneMeshInstance.skinInstance = cloneSkinInstances[skinInstanceIndex];
}
if (meshInstance.morphInstance) {
const morphInstanceIndex = this.morphInstances.indexOf(meshInstance.morphInstance);
cloneMeshInstance.morphInstance = cloneMorphInstances[morphInstanceIndex];
}
cloneMeshInstances.push(cloneMeshInstance);
}
const clone = new Model();
clone.graph = cloneGraph;
clone.meshInstances = cloneMeshInstances;
clone.skinInstances = cloneSkinInstances;
clone.morphInstances = cloneMorphInstances;
clone.getGraph().syncHierarchy();
return clone;
}
/**
* Destroys skinning texture and possibly deletes vertex/index buffers of a model. Mesh is
* reference-counted, so buffers are only deleted if all models with referencing mesh instances
* were deleted. That means all in-scene models + the "base" one (asset.resource) which is
* created when the model is parsed. It is recommended to use asset.unload() instead, which
* will also remove the model from the scene.
*/
destroy() {
const meshInstances = this.meshInstances;
for (let i = 0; i < meshInstances.length; i++) {
meshInstances[i].destroy();
}
this.meshInstances.length = 0;
}
/**
* Generates the necessary internal data for a model to be renderable as wireframe. Once this
* function has been called, any mesh instance in the model can have its renderStyle property
* set to {@link RENDERSTYLE_WIREFRAME}.
*
* @example
* model.generateWireframe();
* for (let i = 0; i < model.meshInstances.length; i++) {
* model.meshInstances[i].renderStyle = pc.RENDERSTYLE_WIREFRAME;
* }
*/
generateWireframe() {
MeshInstance._prepareRenderStyleForArray(this.meshInstances, RENDERSTYLE_WIREFRAME);
}
}
export {
Model
};