var BoneModel3D = function()
{
	this._bones = [];
	this._matrices = [];
	this._matrices2 = [];
	this._matrices3 = [];
	this._vertexBoneBuffer = [];
	this._vertexWeightBuffer = [];
	this._parents = [];
	this._weights = [];
	this._time = 0;
	this._animation = 0;
	this._loop = true;
	this._last = false;
	this._stop = false;
	this._animationMaterials = [];
};
BoneModel3D.prototype = new Model3D();

BoneModel3D.prototype =
{
	init : function()
	{
		Model3D.prototype.init.call(this);
		this._bones = [];
		this._matrices = [];
		this._matrices2 = [];
		this._matrices3 = [];
		this._vertexBoneBuffer = [];
		this._vertexWeightBuffer = [];
		this._parents = [];
		this._weights = [];
		this._time = 0;
		this._animation = 0;
		this._loop = true;
		this._last = false;
		this._stop = false;
		this._animationMaterials = [];
	},
	setMaterial : function(r,g,b,a,dif,amb,emi,spc,power,texture)
	{
		this._materials.push(new Material(r,g,b,a,dif,amb,emi,spc,power,texture));
		this._vertices.push([]);
		this._normals.push([]);
		this._uvs.push([]);
		this._bones.push([]);
		this._parents.push([]);
		this._weights.push([]);
	},
	setVertex : function(x,y,z,nx,ny,nz,material,bone,parent,weight)
	{
		this._vertices[material].push(x,y,z);
		this._normals[material].push(nx,ny,nz);
		this._material.push(~~(material));
		this._bones[material].push(~~(bone));
		if ( parent == null )
		{
			this._parents[material].push(-1);
		}
		else
		{
			this._parents[material].push(~~(parent));
		}
		if ( weight == null )
		{
			this._weights[material].push(1.0);
		}
		else
		{
			this._weights[material].push(weight);
		}
	},
	setBVertex : function(x,y,z,nx,ny,nz,material,bone,weight)
	{
		this._vertices[material].push(x,y,z);
		this._normals[material].push(nx,ny,nz);
		this._material.push(~~(material));
		for ( var i = 0; i < 4; i++ )
		{
			this._bones[material].push(~~(bone[i]));
			this._weights[material].push(weight[i]);
		}
	},
	setUV : function(u,v)
	{
		this._uvs[this._material[this._count]].push(u,v);
		this._count++;
	},
	getVerticesLength : function(index)
	{
		return ~~(this._vertices[index].length/3);
	},
	setMatrix : function(matrix)
	{
		for ( i = 0; i < 16; i++ )
		{
			this._matrices.push(matrix[i]);
		}
	},
	setMatrix2 : function()
	{
		this._matrices2.push(this._matrices);
		this._matrices = [];
	},
	setMatrix3 : function(materials)
	{
		this._animationMaterials.push(materials);
		this._matrices3.push(this._matrices2);
		this._matrices2 = [];
	},
	initBuffers : function()
	{
		Model3D.prototype.initBuffers.call(this);

		for ( var i = 0; i < this._materials.length; i++ )
		{
			if ( this.getVerticesLength(i) > 0 )
			{
				if ( this._parents[i].length <= 0 )
				{
					this._vertexBoneBuffer[i] = _gl.createBuffer();
					_gl.bindBuffer(_gl.ARRAY_BUFFER, this._vertexBoneBuffer[i]);
					_gl.bufferData(_gl.ARRAY_BUFFER, new Float32Array(this._bones[i]), _gl.STATIC_DRAW);
					this._vertexBoneBuffer[i].itemSize = 4;
					this._vertexBoneBuffer[i].numItems = this.getVerticesLength(i);

					this._vertexWeightBuffer[i] = _gl.createBuffer();
					_gl.bindBuffer(_gl.ARRAY_BUFFER, this._vertexWeightBuffer[i]);
					_gl.bufferData(_gl.ARRAY_BUFFER, new Float32Array(this._weights[i]), _gl.STATIC_DRAW);
					this._vertexWeightBuffer[i].itemSize = 4;
					this._vertexWeightBuffer[i].numItems = this.getVerticesLength(i);
				}
				else
				{
					var bones = [];
					var weights = [];
					for ( var b = 0; b < this._bones[i].length; b++ )
					{
						var p = this._parents[i][b];
						var w = this._weights[i][b];
						if ( p < 0 || w > 0.99 )
						{
							bones.push(this._bones[i][b]);
							bones.push(0);
							weights.push(1);
							weights.push(0);
						}
						else
						{
							bones.push(p);
							bones.push(this._bones[i][b]);
							weights.push(w);
							weights.push(1.0-w);
						}
						bones.push(0);
						bones.push(0);
						weights.push(0);
						weights.push(0);
					}
					this._vertexBoneBuffer[i] = _gl.createBuffer();
					_gl.bindBuffer(_gl.ARRAY_BUFFER, this._vertexBoneBuffer[i]);
					_gl.bufferData(_gl.ARRAY_BUFFER, new Float32Array(bones), _gl.STATIC_DRAW);
					this._vertexBoneBuffer[i].itemSize = 4;
					this._vertexBoneBuffer[i].numItems = this.getVerticesLength(i);

					this._vertexWeightBuffer[i] = _gl.createBuffer();
					_gl.bindBuffer(_gl.ARRAY_BUFFER, this._vertexWeightBuffer[i]);
					_gl.bufferData(_gl.ARRAY_BUFFER, new Float32Array(weights), _gl.STATIC_DRAW);
					this._vertexWeightBuffer[i].itemSize = 4;
					this._vertexWeightBuffer[i].numItems = this.getVerticesLength(i);
				}
			}
		}
	},
	draw : function()
	{
		if ( !this._visible )
		{
			return;
		}

		mvPushMatrix();

		_mvMatrix.translate(this._pos);
		_mvMatrix.rotateX(degreeToRadian(this._rotate.x));
		_mvMatrix.rotateY(degreeToRadian(this._rotate.y));
		_mvMatrix.rotateZ(degreeToRadian(this._rotate.z));
		_mvMatrix.scale(this._scale);
		this._mvMatrix = _mvMatrix.copy();
		setMatrixUniforms(_pMatrix._e);

		_gl.uniform1i(_shaderProgram.u_useBone, true);
		_gl.enableVertexAttribArray(_shaderProgram.a_bone);
		_gl.enableVertexAttribArray(_shaderProgram.a_weight);

		if ( !this._stop )
		{
			this._time += _elapsed*30;
		}
		if ( this._time >= this._matrices3[this._animation].length )
		{
			if ( this._last )
			{
				this._time = this._matrices3[this._animation].length - 1;
				this._stop = true;
			}
			else if ( this._loop )
			{
				this._time = 0;
				this._stop = false;
			}
			else
			{
				this._time = 0;
				this._stop = true;
			}
		}
		_gl.uniformMatrix4fv(_shaderProgram.u_boneMatrix, false, this._matrices3[this._animation][~~(this._time)]);
		for ( var i = 0; i < this._materials.length; i++ )
		{
			if ( this.getVerticesLength(i) > 0 )
			{
				_gl.bindBuffer(_gl.ARRAY_BUFFER, this._vertexBoneBuffer[i]);
				_gl.vertexAttribPointer(_shaderProgram.a_bone,this._vertexBoneBuffer[i].itemSize, _gl.FLOAT, false, 0, 0);
				_gl.bindBuffer(_gl.ARRAY_BUFFER, this._vertexWeightBuffer[i]);
				_gl.vertexAttribPointer(_shaderProgram.a_weight,this._vertexWeightBuffer[i].itemSize, _gl.FLOAT, false, 0, 0);
				if ( this._animationMaterials.length > this._animation )
				{
					Model3D.prototype.setVertices.call(this,i,this._animationMaterials[this._animation]);
				}
				else
				{
					Model3D.prototype.setVertices.call(this,i);
				}
				_gl.drawArrays(_gl.TRIANGLES, 0, this.getVerticesLength(i) );
			}
		}

		mvPopMatrix();
	},
	playAnimation : function(animation,loop,last)
	{
		if ( animation >= 0 )
		{
			this._animation = animation % this._matrices3.length;
		}
		this._time = 0;
		this._loop = loop;
		this._last = last;
		this._stop = false;
	},
	forward : function(delta)
	{
		return Model3D.prototype.forward.call(this,delta);
	},
	forward2 : function(delta)
	{
		return Model3D.prototype.forward2.call(this,delta);
	},
	addRotateY : function(delta)
	{
		Model3D.prototype.addRotateY.call(this,delta);
	},
	addRotateY2 : function(delta)
	{
		Model3D.prototype.addRotateY2.call(this,delta);
	},
	dirRadian : function(dest)
	{
		return Model3D.prototype.dirRadian.call(this,dest);
	},
	dirDegree : function(dest)
	{
		return Model3D.prototype.dirDegree.call(this,dest);
	},
	getPos : function()
	{
		return new Vector3D(this._pos.x,this._pos.y,this._pos.z);
	},
	posPlus : function(x,y,z)
	{
		return Model3D.prototype.posPlus.call(this,x,y,z);
	},
	intersect : function(origin,dir)
	{
		return Model3D.prototype.intersect.call(this,origin,dir);
	},
	intersectTriangle : function(origin,dir,v0,v1,v2)
	{
		return Model3D.prototype.intersectTriangle.call(this,origin,dir,v0,v1,v2);
	},
	mousePick : function(x,y)
	{
		return Model3D.prototype.mousePick.call(this,x,y);
	},
	setText : function(text)
	{
		Model3D.prototype.setText.call(this,text);
	},
	fade : function(time)
	{
		Model3D.prototype.fade.call(this,time);
	},
};
