API Docs for:
Show:

File: ../src/components/geometricPrimitive.js

/**
* GeometricPrimitive renders a primitive like a Cube, Sphere, Plane, etc
* @class GeometricPrimitive
* @namespace LS.Components
* @constructor
* @param {String} object to configure from
*/

function GeometricPrimitive( o )
{
	this.enabled = true;
	this._size = 10;
	this._subdivisions = 10;
	this._geometry = GeometricPrimitive.CUBE;
	this._custom_mesh = null; //used for meshes that must be stored with the JSON
	this._primitive = -1; //GL.POINTS, GL.LINES, GL.TRIANGLES, etc...
	this._point_size = 0.1;

	this._version = 1;
	this._mesh = null;
	this._mesh_version = 0;

	if(o)
		this.configure(o);
}


/**
* The shape to render, valid values are: LS.Components.GeometricPrimitive.CUBE,PLANE,CYLINDER,SPHERE,CIRCLE,HEMISPHERE,ICOSAHEDRON,CONE,QUAD
* @property geometry {enum}
* @default LS.Components.GeometricPrimitive.CUBE
*/
Object.defineProperty( GeometricPrimitive.prototype, 'geometry', {
	get: function() { return this._geometry; },
	set: function(v) { 
		if( this._geometry == v )
			return;
		v = (v === undefined || v === null ? -1 : v|0);
		if( !GeometricPrimitive.VALID[v] )
			return;
		this._geometry = v;
		this._version++;
	},
	enumerable: true
});

/**
* The size of the primitive (the global scale)
* @property size {Number}
* @default 10
*/
Object.defineProperty( GeometricPrimitive.prototype, 'size', {
	get: function() { return this._size; },
	set: function(v) { 
		if( this._size == v )
			return;
		this._size = v;
		this._version++;
	},
	enumerable: true
});

Object.defineProperty( GeometricPrimitive.prototype, 'subdivisions', {
	get: function() { return this._subdivisions; },
	set: function(v) { 
		if( this._subdivisions == v )
			return;
		this._subdivisions = v;
		this._version++;
	},
	enumerable: true
});

/**
* The GL primitive to use (LINES,LINE_STRIP,TRIANGLES,TRIANGLE_FAN
* @property primitive {enum}
* @default 10
*/
Object.defineProperty( GeometricPrimitive.prototype, 'primitive', {
	get: function() { return this._primitive; },
	set: function(v) { 
		v = (v === undefined || v === null ? -1 : v|0);
		if(v != -1 && v != 0 && v!= 1 && v!= 4 && v!= 10)
			return;
		this._primitive = v;
	},
	enumerable: true
});

Object.defineProperty( GeometricPrimitive.prototype, 'point_size', {
	get: function() { return this._point_size; },
	set: function(v) { 
		if( this._point_size == v )
			return;
		this._point_size = v;
	},
	enumerable: true
});

//assign a custom mesh
Object.defineProperty( GeometricPrimitive.prototype, 'mesh', {
	get: function() { return this._custom_mesh || this._mesh; },
	set: function(v) { 
		if(v && v.constructor !== GL.Mesh)
			throw("mesh must be a GL.Mesh");
		this._custom_mesh = v;
		if(v)
			this._geometry = GeometricPrimitive.CUSTOM;
	},
	enumerable: false
});


GeometricPrimitive.CUBE = 1;
GeometricPrimitive.PLANE = 2;
GeometricPrimitive.CYLINDER = 3;
GeometricPrimitive.SPHERE = 4;
GeometricPrimitive.CIRCLE = 5;
GeometricPrimitive.HEMISPHERE = 6;
GeometricPrimitive.ICOSAHEDRON = 7;
GeometricPrimitive.CONE = 8;
GeometricPrimitive.QUAD = 9;
GeometricPrimitive.CUSTOM = 100;

GeometricPrimitive.VALID = { 1:"CUBE", 2:"PLANE", 3:"CYLINDER", 4:"SPHERE", 5:"CIRCLE", 6:"HEMISPHERE", 7:"ICOSAHEDRON", 8: "CONE", 9:"QUAD", 100:"CUSTOM" };

//Warning : if you add more primitives, be careful with the setter, it doesnt allow values bigger than 7

GeometricPrimitive.icon = "mini-icon-cube.png";
GeometricPrimitive["@geometry"] = { type:"enum", values: {"Cube":GeometricPrimitive.CUBE, "Plane": GeometricPrimitive.PLANE, "Cylinder":GeometricPrimitive.CYLINDER, "Sphere":GeometricPrimitive.SPHERE, "Cone":GeometricPrimitive.CONE, "Icosahedron":GeometricPrimitive.ICOSAHEDRON, "Circle":GeometricPrimitive.CIRCLE, "Hemisphere":GeometricPrimitive.HEMISPHERE, "Quad": GeometricPrimitive.QUAD, "Custom": GeometricPrimitive.CUSTOM }};
GeometricPrimitive["@primitive"] = {widget:"enum", values: {"Default":-1, "Points": 0, "Lines":1, "Triangles":4, "Wireframe":10 }};
GeometricPrimitive["@subdivisions"] = { type:"number", step:1, min:1, precision: 0 };
GeometricPrimitive["@point_size"] = { type:"number", step:0.001 };

//we bind to onAddedToNode because the event is triggered per node so we know which RIs belong to which node
GeometricPrimitive.prototype.onAddedToNode = function( node )
{
	LEvent.bind( node, "collectRenderInstances", this.onCollectInstances, this);
}

GeometricPrimitive.prototype.onRemovedFromNode = function( node )
{
	LEvent.unbind( node, "collectRenderInstances", this.onCollectInstances, this);
}

GeometricPrimitive.prototype.serialize = function()
{
	var r = LS.BaseComponent.prototype.serialize.call(this);
	if(this._geometry == GeometricPrimitive.CUSTOM && this._custom_mesh)
		r.custom_mesh = this._custom_mesh.toJSON();

	return r;
}

GeometricPrimitive.prototype.configure = function(o)
{
	LS.BaseComponent.prototype.configure.call(this,o);

	//legacy
	if(this._geometry == GeometricPrimitive.PLANE && o.align_z === false )
		this._geometry = GeometricPrimitive.QUAD;

	if(o.geometry == GeometricPrimitive.CUSTOM && o.custom_mesh)
	{
		if(!this._custom_mesh)
			this._custom_mesh = new GL.Mesh();
		this._custom_mesh.fromJSON( o.custom_mesh );
	}

	this._version++;
}

GeometricPrimitive.prototype.updateMesh = function()
{
	var subdivisions = Math.max(0,this.subdivisions|0);

	switch (this._geometry)
	{
		case GeometricPrimitive.CUBE: 
			this._mesh = GL.Mesh.cube({size: this.size, normals:true,coords:true});
			break;
		case GeometricPrimitive.PLANE:
			this._mesh = GL.Mesh.plane({size: this.size, xz: true, detail: subdivisions, normals:true,coords:true});
			break;
		case GeometricPrimitive.CYLINDER:
			this._mesh = GL.Mesh.cylinder({size: this.size, subdivisions: subdivisions, normals:true,coords:true});
			break;
		case GeometricPrimitive.SPHERE:
			this._mesh = GL.Mesh.sphere({size: this.size, "long": subdivisions, lat: subdivisions, normals:true,coords:true});
			break;
		case GeometricPrimitive.CIRCLE:
			this._mesh = GL.Mesh.circle({size: this.size, slices: subdivisions, normals:true, coords:true});
			break;
		case GeometricPrimitive.HEMISPHERE:
			this._mesh = GL.Mesh.sphere({size: this.size, "long": subdivisions, lat: subdivisions, normals:true, coords:true, hemi: true});
			break;
		case GeometricPrimitive.ICOSAHEDRON:
			this._mesh = GL.Mesh.icosahedron({size: this.size, subdivisions:subdivisions });
			break;
		case GeometricPrimitive.CONE:
			this._mesh = GL.Mesh.cone({radius: this.size, height: this.size, subdivisions:subdivisions });
			break;
		case GeometricPrimitive.QUAD:
			this._mesh = GL.Mesh.plane({size: this.size, xz: false, detail: subdivisions, normals:true, coords:true });
			break;
		case GeometricPrimitive.CUSTOM:
			this._mesh = this._custom_mesh;
			break;
	}

	this._mesh_version = this._version;
}

/**
* Assigns a mesh as custom mesh and sets the geometry to CUSTOM
* @method setCustomMesh
* @param {GL.Mesh} mesh the mesh to use as custom mesh
*/
GeometricPrimitive.prototype.setCustomMesh = function( mesh )
{
	this._geometry = GeometricPrimitive.CUSTOM;
	this._custom_mesh = mesh;
	this._mesh = this._custom_mesh;
}

//GeometricPrimitive.prototype.getRenderInstance = function()
GeometricPrimitive.prototype.onCollectInstances = function(e, instances)
{
	if(!this.enabled)
		return;

	var mesh = null;
	if(!this._root)
		return;

	var RI = this._render_instance;
	if(!RI)
		this._render_instance = RI = new LS.RenderInstance(this._root, this);

	if(!this._mesh || this._version != this._mesh_version )
		this.updateMesh();

	if(!this._mesh) //could happend if custom mesh is null
		return;

	//assigns matrix, layers
	RI.fromNode( this._root );
	RI.setMesh( this._mesh, this._primitive );
	this._root.mesh = this._mesh;
	
	RI.setMaterial( this.material || this._root.getMaterial() );

	//remove one day...
	if(this.primitive == gl.POINTS)
	{
		RI.uniforms.u_point_size = this.point_size;
		//RI.query.macros["USE_POINTS"] = "";
	}

	instances.push(RI);
}

LS.registerComponent( GeometricPrimitive );