578 lines
13 KiB
JavaScript
578 lines
13 KiB
JavaScript
|
/**
|
||
|
* Scene Superset - The apiScene properties get moved into the Scene object itself, and then the instance is
|
||
|
* created
|
||
|
* @param graphics
|
||
|
* @param apiScene R3.D3.API.Scene
|
||
|
* @constructor
|
||
|
*/
|
||
|
R3.D3.Scene = function (
|
||
|
graphics,
|
||
|
apiScene
|
||
|
) {
|
||
|
this.graphics = graphics;
|
||
|
this.graphics.isNotThreeThrow();
|
||
|
|
||
|
if (R3.Utils.UndefinedOrNull(apiScene)) {
|
||
|
apiScene = {};
|
||
|
}
|
||
|
|
||
|
R3.D3.API.Scene.call(
|
||
|
this,
|
||
|
apiScene.id,
|
||
|
apiScene.name,
|
||
|
apiScene.meshes,
|
||
|
apiScene.lights,
|
||
|
apiScene.textures,
|
||
|
apiScene.materials,
|
||
|
apiScene.images,
|
||
|
apiScene.fog,
|
||
|
apiScene.showGrid,
|
||
|
apiScene.showAxis,
|
||
|
apiScene.gridSize,
|
||
|
apiScene.gridColor,
|
||
|
apiScene.camera,
|
||
|
apiScene.parentEntity
|
||
|
);
|
||
|
|
||
|
this.textures = this.textures.map(
|
||
|
function(apiTexture) {
|
||
|
|
||
|
if (typeof apiTexture === 'string') {
|
||
|
return apiTexture;
|
||
|
}
|
||
|
|
||
|
return new R3.D3.Texture(
|
||
|
this.graphics,
|
||
|
apiTexture
|
||
|
);
|
||
|
|
||
|
}.bind(this)
|
||
|
);
|
||
|
|
||
|
this.materials = this.materials.map(
|
||
|
function(apiMaterial) {
|
||
|
|
||
|
if (typeof apiMaterial === 'string') {
|
||
|
return apiMaterial;
|
||
|
}
|
||
|
|
||
|
return new R3.D3.Material(
|
||
|
this.graphics,
|
||
|
apiMaterial
|
||
|
);
|
||
|
|
||
|
}.bind(this)
|
||
|
);
|
||
|
|
||
|
this.images = this.images.map(
|
||
|
function(apiImage) {
|
||
|
|
||
|
if (typeof apiImage === 'string') {
|
||
|
return apiImage;
|
||
|
}
|
||
|
|
||
|
return new R3.Image(
|
||
|
this.graphics,
|
||
|
apiImage
|
||
|
);
|
||
|
|
||
|
}.bind(this)
|
||
|
);
|
||
|
|
||
|
if (this.fog instanceof R3.D3.API.Fog) {
|
||
|
this.fog = new R3.D3.Fog(
|
||
|
this.graphics,
|
||
|
this.fog
|
||
|
)
|
||
|
};
|
||
|
|
||
|
this.gridColor = new R3.Color(
|
||
|
this.graphics,
|
||
|
this.gridColor,
|
||
|
this
|
||
|
);
|
||
|
|
||
|
/**
|
||
|
* Runtime scenes have helpers (just used to store which helper belongs to which scene)
|
||
|
* @type {Array}
|
||
|
*/
|
||
|
this.helpers = [];
|
||
|
|
||
|
this.clones = [];
|
||
|
|
||
|
this.grid = [];
|
||
|
|
||
|
this.axis = [];
|
||
|
|
||
|
this.storeClones = false;
|
||
|
|
||
|
R3.Component.call(
|
||
|
this,
|
||
|
{
|
||
|
'meshes' : [R3.D3.Mesh],
|
||
|
'lights' : [R3.D3.Light],
|
||
|
'textures' : [R3.D3.Texture],
|
||
|
'materials' : [R3.D3.Material],
|
||
|
'images' : [R3.Image],
|
||
|
'fog' : R3.D3.Fog,
|
||
|
'camera' : R3.D3.Camera
|
||
|
}
|
||
|
);
|
||
|
};
|
||
|
|
||
|
R3.D3.Scene.prototype = Object.create(R3.Component.prototype);
|
||
|
R3.D3.Scene.prototype.constructor = R3.D3.Scene;
|
||
|
|
||
|
/**
|
||
|
* Creates an instance scene
|
||
|
* @returns {THREE.Scene}
|
||
|
*/
|
||
|
R3.D3.Scene.prototype.createInstance = function() {
|
||
|
|
||
|
this.instance = new THREE.Scene();
|
||
|
|
||
|
this.instance.name = this.name;
|
||
|
|
||
|
if (this.fog && this.fog.instance) {
|
||
|
this.instance.fog = this.fog.instance;
|
||
|
}
|
||
|
|
||
|
this.meshes.map(
|
||
|
function(mesh) {
|
||
|
|
||
|
if (R3.Utils.UndefinedOrNull(mesh)) {
|
||
|
throw new Error('no mesh');
|
||
|
}
|
||
|
|
||
|
if (R3.Utils.UndefinedOrNull(mesh.instance)) {
|
||
|
throw new Error('no mesh instance');
|
||
|
}
|
||
|
|
||
|
this.instance.add(mesh.instance);
|
||
|
|
||
|
mesh.parentScene = this;
|
||
|
|
||
|
}.bind(this)
|
||
|
);
|
||
|
|
||
|
this.lights.map(
|
||
|
function(light) {
|
||
|
|
||
|
|
||
|
if (R3.Utils.UndefinedOrNull(light)) {
|
||
|
throw new Error('no light');
|
||
|
}
|
||
|
|
||
|
if (R3.Utils.UndefinedOrNull(light.instance)) {
|
||
|
throw new Error('no light instance');
|
||
|
}
|
||
|
|
||
|
this.instance.add(light.instance);
|
||
|
|
||
|
light.parentScene = this;
|
||
|
|
||
|
}.bind(this)
|
||
|
);
|
||
|
|
||
|
if (this.showGrid) {
|
||
|
this.drawGrid();
|
||
|
}
|
||
|
|
||
|
if (this.showAxis) {
|
||
|
this.drawAxis();
|
||
|
}
|
||
|
|
||
|
R3.Component.prototype.createInstance.call(this);
|
||
|
|
||
|
};
|
||
|
|
||
|
R3.D3.Scene.prototype.updateInstance = function(property) {
|
||
|
|
||
|
if (property === 'name') {
|
||
|
this.instance.name = this.name;
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
if (property === 'fog') {
|
||
|
if (this.fog && this.fog.instance !== this.instance.fog) {
|
||
|
this.instance.fog = this.fog.instance;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (property === 'meshes') {
|
||
|
|
||
|
/**
|
||
|
* Add missing meshes
|
||
|
*/
|
||
|
this.meshes.map(
|
||
|
function (mesh) {
|
||
|
if (this.instance.children.indexOf(mesh.instance === -1)) {
|
||
|
this.instance.add(mesh.instance);
|
||
|
}
|
||
|
}.bind(this)
|
||
|
);
|
||
|
}
|
||
|
|
||
|
if (property === 'lights') {
|
||
|
|
||
|
/**
|
||
|
* Add missing lights
|
||
|
*/
|
||
|
this.lights.map(
|
||
|
function (light) {
|
||
|
if (this.instance.children.indexOf(light.instance) === -1) {
|
||
|
this.instance.add(light.instance);
|
||
|
}
|
||
|
}.bind(this)
|
||
|
);
|
||
|
}
|
||
|
|
||
|
if (
|
||
|
property === 'meshes' ||
|
||
|
property === 'lights'
|
||
|
) {
|
||
|
/**
|
||
|
* Remove extra meshes and lights
|
||
|
*/
|
||
|
this.instance.children.map(
|
||
|
function (instanceObject) {
|
||
|
|
||
|
var instanceMeshes = this.meshes.map(
|
||
|
function (mesh) {
|
||
|
return mesh.instance;
|
||
|
}
|
||
|
);
|
||
|
|
||
|
var instanceLights = this.lights.map(
|
||
|
function (light) {
|
||
|
return light.instance;
|
||
|
}
|
||
|
);
|
||
|
|
||
|
if (
|
||
|
(
|
||
|
instanceObject instanceof THREE.Mesh ||
|
||
|
instanceObject instanceof THREE.Light
|
||
|
) &&
|
||
|
(
|
||
|
instanceLights.indexOf(instanceObject) === -1 &&
|
||
|
instanceMeshes.indexOf(instanceObject) === -1
|
||
|
)
|
||
|
) {
|
||
|
this.instance.remove(instanceObject);
|
||
|
}
|
||
|
|
||
|
}.bind(this)
|
||
|
);
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
if (
|
||
|
property === 'showGrid' ||
|
||
|
property === 'gridSize' ||
|
||
|
property === 'gridColor'
|
||
|
) {
|
||
|
if (this.showGrid) {
|
||
|
this.drawGrid();
|
||
|
} else {
|
||
|
this.removeGrid();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (property === 'showAxis') {
|
||
|
if (this.showAxis) {
|
||
|
this.drawAxis();
|
||
|
} else {
|
||
|
this.removeAxis();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
R3.Component.prototype.updateInstance.call(this, property);
|
||
|
};
|
||
|
|
||
|
/**
|
||
|
* Converts a R3.D3.Scene to a R3.D3.API.Scene
|
||
|
* @returns {R3.D3.API.Scene}
|
||
|
*/
|
||
|
R3.D3.Scene.prototype.toApiObject = function() {
|
||
|
|
||
|
var apiMeshes = [];
|
||
|
|
||
|
if (this.storeClones) {
|
||
|
this.clones.map(
|
||
|
function (clone) {
|
||
|
R3.Utils.PushUnique(
|
||
|
apiMeshes,
|
||
|
R3.Utils.IdOrNull(clone)
|
||
|
);
|
||
|
}
|
||
|
);
|
||
|
}
|
||
|
|
||
|
this.meshes.map(
|
||
|
function(mesh) {
|
||
|
R3.Utils.PushUnique(
|
||
|
apiMeshes,
|
||
|
R3.Utils.IdOrNull(mesh)
|
||
|
);
|
||
|
}
|
||
|
);
|
||
|
|
||
|
return new R3.D3.API.Scene(
|
||
|
this.id,
|
||
|
this.name,
|
||
|
apiMeshes,
|
||
|
this.lights.map(
|
||
|
function(light) {
|
||
|
return R3.Utils.IdOrNull(light);
|
||
|
}
|
||
|
),
|
||
|
this.textures.map(
|
||
|
function(texture) {
|
||
|
return R3.Utils.IdOrNull(texture);
|
||
|
}
|
||
|
),
|
||
|
this.materials.map(
|
||
|
function(material) {
|
||
|
return R3.Utils.IdOrNull(material);
|
||
|
}
|
||
|
),
|
||
|
this.images.map(
|
||
|
function(image) {
|
||
|
return R3.Utils.IdOrNull(image);
|
||
|
}
|
||
|
),
|
||
|
R3.Utils.IdOrNull(this.fog),
|
||
|
this.showGrid,
|
||
|
this.showAxis,
|
||
|
this.gridSize,
|
||
|
this.gridColor.toApiObject(),
|
||
|
R3.Utils.IdOrNull(this.camera),
|
||
|
R3.Utils.IdOrNull(this.parentEntity)
|
||
|
);
|
||
|
};
|
||
|
|
||
|
/**
|
||
|
* Adds a mesh to the scene
|
||
|
* @param object R3.D3.Mesh
|
||
|
*/
|
||
|
R3.D3.Scene.prototype.addObject = function(object) {
|
||
|
|
||
|
if (object instanceof R3.D3.Mesh) {
|
||
|
if (this.meshes.indexOf(object.id) === -1) {
|
||
|
R3.Utils.PushUnique(this.meshes, object);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (object instanceof R3.D3.Light) {
|
||
|
if (this.lights.indexOf(object.id) === -1) {
|
||
|
R3.Utils.PushUnique(this.lights, object);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
object.parentScene = this;
|
||
|
|
||
|
if (
|
||
|
this.instance &&
|
||
|
object.instance
|
||
|
) {
|
||
|
if (this.instance.children.indexOf(object.instance) === -1) {
|
||
|
this.instance.add(object.instance);
|
||
|
}
|
||
|
} else {
|
||
|
// console.warn('either scene or mesh instance not ready');
|
||
|
}
|
||
|
|
||
|
// if (this.parentEntity) {
|
||
|
// this.parentEntity.addComponent(object);
|
||
|
// }
|
||
|
|
||
|
};
|
||
|
|
||
|
R3.D3.Scene.prototype.addClone = function(component) {
|
||
|
|
||
|
if (component instanceof R3.D3.Mesh ||
|
||
|
component instanceof R3.D3.Light
|
||
|
) {
|
||
|
if (this.instance && component.instance) {
|
||
|
if (this.instance.children.indexOf(component.instance) === -1) {
|
||
|
this.instance.add(component.instance);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
component.isClone = true;
|
||
|
|
||
|
R3.Utils.PushUnique(this.clones, component);
|
||
|
|
||
|
var index = this.meshes.indexOf(component);
|
||
|
|
||
|
if (index !== -1) {
|
||
|
this.meshes.splice(index, 1);
|
||
|
}
|
||
|
|
||
|
component.parentScene = this;
|
||
|
}
|
||
|
};
|
||
|
|
||
|
/**
|
||
|
*
|
||
|
* @param object
|
||
|
*/
|
||
|
R3.D3.Scene.prototype.removeObject = function(object) {
|
||
|
|
||
|
var index = -1;
|
||
|
|
||
|
if (object instanceof R3.D3.Mesh) {
|
||
|
|
||
|
index = this.meshes.indexOf(object);
|
||
|
if (index !== -1) {
|
||
|
this.meshes.splice(index, 1);
|
||
|
}
|
||
|
|
||
|
index = this.clones.indexOf(object);
|
||
|
if (index !== -1) {
|
||
|
this.clones.splice(index, 1);
|
||
|
}
|
||
|
|
||
|
} else if (object instanceof R3.D3.Light) {
|
||
|
|
||
|
index = this.lights.indexOf(object);
|
||
|
if (index !== -1) {
|
||
|
this.lights.splice(index, 1);
|
||
|
}
|
||
|
|
||
|
index = this.clones.indexOf(object);
|
||
|
if (index !== -1) {
|
||
|
this.clones.splice(index, 1);
|
||
|
}
|
||
|
|
||
|
} else {
|
||
|
console.warn('Cannot remove this object - what is this ?' + object.toString());
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
if (this.instance.children.indexOf(object.instance) !== -1) {
|
||
|
this.instance.remove(object.instance);
|
||
|
} else {
|
||
|
console.warn('no scene instance');
|
||
|
}
|
||
|
|
||
|
if (object.parentScene === this) {
|
||
|
object.parentScene = null;
|
||
|
}
|
||
|
//
|
||
|
// if (this.parentEntity) {
|
||
|
// this.parentEntity.removeComponent(object);
|
||
|
// }
|
||
|
// this.buildIdToObject();
|
||
|
};
|
||
|
|
||
|
R3.D3.Scene.prototype.drawGrid = function() {
|
||
|
|
||
|
this.removeGrid();
|
||
|
|
||
|
var lineMaterial = new THREE.LineBasicMaterial({
|
||
|
color: this.gridColor.toHex(),
|
||
|
linewidth: 1
|
||
|
});
|
||
|
|
||
|
for (var y = -this.gridSize; y <= this.gridSize; y += 1) {
|
||
|
|
||
|
var Xgeometry = new THREE.Geometry();
|
||
|
Xgeometry.vertices.push(
|
||
|
new THREE.Vector3( y, 0, this.gridSize * -1 ),
|
||
|
new THREE.Vector3( y, 0, this.gridSize )
|
||
|
);
|
||
|
|
||
|
var lineX = new THREE.Line(Xgeometry, lineMaterial);
|
||
|
|
||
|
this.instance.add(lineX);
|
||
|
|
||
|
this.grid.push(lineX);
|
||
|
|
||
|
var Ygeometry = new THREE.Geometry();
|
||
|
Ygeometry.vertices.push(
|
||
|
new THREE.Vector3( this.gridSize * -1 , 0, y ),
|
||
|
new THREE.Vector3( this.gridSize, 0, y )
|
||
|
);
|
||
|
|
||
|
var lineY = new THREE.Line(Ygeometry, lineMaterial);
|
||
|
|
||
|
this.instance.add(lineY);
|
||
|
|
||
|
this.grid.push(lineY);
|
||
|
}
|
||
|
};
|
||
|
|
||
|
R3.D3.Scene.prototype.removeGrid = function() {
|
||
|
this.grid.map(
|
||
|
function(object) {
|
||
|
this.instance.remove(object);
|
||
|
}.bind(this)
|
||
|
);
|
||
|
};
|
||
|
|
||
|
R3.D3.Scene.prototype.drawAxis = function() {
|
||
|
|
||
|
this.removeAxis();
|
||
|
|
||
|
var Xmaterial = new THREE.LineBasicMaterial({
|
||
|
color: 0xff0000,
|
||
|
linewidth: 2
|
||
|
});
|
||
|
|
||
|
var Xgeometry = new THREE.Geometry();
|
||
|
Xgeometry.vertices.push(
|
||
|
new THREE.Vector3( 0, 0, 0 ),
|
||
|
new THREE.Vector3( 100, 0, 0 )
|
||
|
);
|
||
|
|
||
|
var lineX = new THREE.Line(Xgeometry, Xmaterial);
|
||
|
|
||
|
this.instance.add(lineX);
|
||
|
|
||
|
this.axis.push(lineX);
|
||
|
|
||
|
var Ymaterial = new THREE.LineBasicMaterial({
|
||
|
color: 0x00ff00,
|
||
|
linewidth: 2
|
||
|
});
|
||
|
|
||
|
var Ygeometry = new THREE.Geometry();
|
||
|
Ygeometry.vertices.push(
|
||
|
new THREE.Vector3( 0, 0, 0 ),
|
||
|
new THREE.Vector3( 0, 100, 0 )
|
||
|
);
|
||
|
|
||
|
var lineY = new THREE.Line(Ygeometry, Ymaterial);
|
||
|
|
||
|
this.instance.add(lineY);
|
||
|
|
||
|
this.axis.push(lineY);
|
||
|
|
||
|
var Zmaterial = new THREE.LineBasicMaterial({
|
||
|
color: 0x0000ff,
|
||
|
linewidth: 2
|
||
|
});
|
||
|
|
||
|
var Zgeometry = new THREE.Geometry();
|
||
|
Zgeometry.vertices.push(
|
||
|
new THREE.Vector3( 0, 0, 0 ),
|
||
|
new THREE.Vector3( 0, 0, 100 )
|
||
|
);
|
||
|
|
||
|
var lineZ = new THREE.Line(Zgeometry, Zmaterial);
|
||
|
|
||
|
this.instance.add(lineZ);
|
||
|
|
||
|
this.axis.push(lineZ);
|
||
|
};
|
||
|
|
||
|
R3.D3.Scene.prototype.removeAxis = function() {
|
||
|
this.axis.map(
|
||
|
function(object) {
|
||
|
this.instance.remove(object);
|
||
|
}.bind(this)
|
||
|
);
|
||
|
};
|