/**
* jslint browser: true
*/
/**
* Creates new object with default values
* @class
* @constructor
*/
Ayce.Object3D = function () {
var scope = this;
//Position and Rotation of the object
this.position = new Ayce.Vector3();
this.rotation = new Ayce.Quaternion();
var positionGlobal = new Ayce.Vector3();
var rotationGlobal = new Ayce.Quaternion();
var rotationMatrix = new Ayce.Matrix4();
this.scale = new Ayce.Vector3(1, 1, 1);
this.modelMatrix = new Ayce.Matrix4();
this.parent = null;
this.parentPositionWeight = new Ayce.Vector3(1, 1, 1);
this.parentRotationWeight = new Ayce.Vector3(1, 1, 1);
//Arrays for Buffer
this.vertices = null;
this.normals = null;
this.textureCoords = null;
this.textureIndices = null;
this.colors = null;
this.indices = null;
this.transparent = false;
this.isWireframe = false;
this.twoFaceTransparency = false;
//Buffer
this.buffer = null;
//Texture Image
this.imageSrc = null;
//Shader
this.shader = null;
this.shaderAttributes = null;
this.shaderUniforms = null;
this.useFragmentLighting = false;
this.specularMap = null;
this.normalMap = null;
this.useSpecularLighting = false;
this.shininess = 1.0;
//Sound
this.soundFile = null;
this.sound = null;
//Skybox
this.isSkybox = false;
//Bounding
this.boundingBox = null;
this.boundingSphere = null;
//Movement
this.gravity = null;
this.velocity = new Ayce.Vector3();
this.collision = false;
this.useBoundingSphere = false;
this.collideWith = null;
this.onCollision = null;
var lastUpdateTime = Ayce.Timer.prototype.getCurrentTimeMs();
//update
this.onUpdate = null;
//Transparent sorting
this.renderPriority = null;
//Hide or hide object
this.visible = true;
//Log generated shader to console
this.logVertexShader = false;
this.logFragmentShader = false;
/**
* Description
*/
this.calcBoundingBox = function(){
if(!this.vertices)console.error("No Vertices set. Can't calc Bounding Box.");
calcGlobalPosition();
var xMin = this.vertices[0];
var xMax = this.vertices[0];
var yMin = this.vertices[1];
var yMax = this.vertices[1];
var zMin = this.vertices[2];
var zMax = this.vertices[2];
for(var i=0; i < this.vertices.length; i+=3){
var x = this.vertices[i+0];
var y = this.vertices[i+1];
var z = this.vertices[i+2];
if(x > xMax)xMax = x;
if(x < xMin)xMin = x;
if(y > yMax)yMax = y;
if(y < yMin)yMin = y;
if(z > zMax)zMax = z;
if(z < zMin)zMin = z;
}
var a = xMax - xMin;
var b = yMax - yMin;
var c = zMax - zMin;
this.boundingBox = new Ayce.Geometry.Box(a, b, c);
this.boundingBox.position = positionGlobal;
this.boundingBox.offset = new Ayce.Vector3(xMin, yMin, zMin);
this.boundingBox.rotation = rotationGlobal;
this.boundingBox.scale = this.scale;
};
/**
* Description
*/
this.calcBoundingSphere = function(){
calcGlobalPosition();
var s = this.scale;
var xMin = this.vertices[0]*s.x;
var xMax = this.vertices[0]*s.x;
var yMin = this.vertices[1]*s.y;
var yMax = this.vertices[1]*s.y;
var zMin = this.vertices[2]*s.z;
var zMax = this.vertices[2]*s.z;
var i, x, y, z;
for(i=0; i < this.vertices.length; i+=3){
x = this.vertices[i+0]*s.x;
y = this.vertices[i+1]*s.y;
z = this.vertices[i+2]*s.z;
if(x > xMax)xMax = x;
if(x < xMin)xMin = x;
if(y > yMax)yMax = y;
if(y < yMin)yMin = y;
if(z > zMax)zMax = z;
if(z < zMin)zMin = z;
}
var centerPoint = new Ayce.Vector3((xMax+xMin)/2, (yMax+yMin)/2, (zMax+zMin)/2);
var radius = 0;
for(i=0; i < this.vertices.length; i+=3){
x = this.vertices[i+0]*this.scale.x;
y = this.vertices[i+1]*this.scale.y;
z = this.vertices[i+2]*this.scale.z;
var r = Ayce.Vector3.prototype.distance(centerPoint, new Ayce.Vector3(x, y, z));
if(r > radius)radius = r;
}
this.boundingSphere = new Ayce.Geometry.Sphere(radius);
this.boundingSphere.position = positionGlobal;
this.boundingSphere.offset = centerPoint;
this.boundingSphere.rotation = rotationGlobal;
};
/**
* Description
*/
this.update = function(){
var currentTime = Ayce.Timer.prototype.getCurrentTimeMs();
var elapsedTime = currentTime-lastUpdateTime;
//Update Movement
var g = this.gravity;
var v = this.velocity;
if((g || (v.x !== 0 || v.y !== 0 || v.z !== 0)) && elapsedTime > 0){
var p = elapsedTime/1000.0;
if(g){
if((g.x > 0 && v.x < g.x) || (g.x < 0 && v.x > g.x))v.x = (v.x + g.x*p);
if((g.y > 0 && v.y < g.y) || (g.y < 0 && v.y > g.y))v.y = (v.y + g.y*p);
if((g.z > 0 && v.z < g.z) || (g.z < 0 && v.z > g.z))v.z = (v.z + g.z*p);
}
this.position.x += v.x*p;
this.position.y += v.y*p;
this.position.z += v.z*p;
calcGlobalPosition();
if(this.collision && this.collideWith){
for(var i=0; i < this.collideWith.length; i++){
var check = this.collideWith[i];
var x = (this.boundingSphere.position.x+this.boundingSphere.offset.x) - (check.boundingSphere.position.x+check.boundingSphere.offset.x);
var y = (this.boundingSphere.position.y+this.boundingSphere.offset.y) - (check.boundingSphere.position.y+check.boundingSphere.offset.y);
var z = (this.boundingSphere.position.z+this.boundingSphere.offset.z) - (check.boundingSphere.position.z+check.boundingSphere.offset.z);
var d = Math.sqrt (x * x + y * y + z * z);
var r = this.boundingSphere.r + check.boundingSphere.r;
if(d > r*1.3)continue;//TODO fix -> 1.3
var collisionCheck;
if(check.useBoundingSphere && this.useBoundingSphere){
collisionCheck = Ayce.Geometry.prototype.sphereSphereCollision(this.boundingSphere, check.boundingSphere);
}
else if(check.useBoundingSphere){
collisionCheck = Ayce.Geometry.prototype.boxSphereCollision(this.boundingBox, check.boundingSphere, true);
}
else if(this.useBoundingSphere){
collisionCheck = Ayce.Geometry.prototype.boxSphereCollision(check.boundingBox, this.boundingSphere);
}
else{
collisionCheck = Ayce.Geometry.prototype.boxBoxCollision(this.boundingBox, check.boundingBox);
}
if(collisionCheck){
this.position.subtract(collisionCheck.x, collisionCheck.y, collisionCheck.z);
if(this.onCollision){
var collisionData = {
collisionWith: check,
collisionVector: collisionCheck.negate()
};
this.onCollision(collisionData);
}
}
}
}
}
lastUpdateTime = currentTime;
calcGlobalPosition();
//Create ModelViewMatrix
this.modelMatrix.identity();
this.modelMatrix.applyScale(this.scale.x, this.scale.y, this.scale.z);
rotationGlobal.toRotationMatrix(rotationMatrix);
this.modelMatrix.apply(rotationMatrix);
this.modelMatrix.applyTranslation(positionGlobal.x, positionGlobal.y, positionGlobal.z);
if(this.onUpdate)this.onUpdate();
};
var poolVec = new Ayce.Vector3();
var poolQuat = new Ayce.Quaternion();
var calcGlobalPosition = function(){
if(scope.parent){
//rotation
var r = scope.parent.getGlobalRotation();
var qW = scope.parentRotationWeight;
rotationGlobal.x = r.x * qW.x;
rotationGlobal.y = r.y * qW.y;
rotationGlobal.z = r.z * qW.z;
rotationGlobal.w = r.w;
Ayce.Quaternion.prototype.copyToQuaternion(rotationGlobal, poolQuat);
rotationGlobal.getConjugate(poolQuat);
rotationGlobal.normalize();
rotationGlobal.multiply(scope.rotation, rotationGlobal);
//position
var pP = scope.parent.getGlobalPosition();
var pW = scope.parentPositionWeight;
poolVec.x = scope.position.x;
poolVec.y = scope.position.y;
poolVec.z = scope.position.z;
poolQuat.rotatePoint(poolVec);
positionGlobal.x = pP.x*pW.x + poolVec.x;
positionGlobal.y = pP.y*pW.y + poolVec.y;
positionGlobal.z = pP.z*pW.z + poolVec.z;
}
else{
Ayce.Vector3.prototype.copyToVector(scope.position, positionGlobal);
Ayce.Quaternion.prototype.copyToQuaternion(scope.rotation, rotationGlobal);
}
};
/**
* Description
* @return positionGlobal
*/
this.getGlobalPosition = function(){
return positionGlobal;
};
/**
* Description
* @return rotationGlobal
*/
this.getGlobalRotation = function(){
return rotationGlobal;
};
};
Ayce.Object3D.prototype = {
/**
* Description
* @param {} attributeName
* @param {} valueLength
* @param {} sourceArray
*/
addShaderAttribute: function(attributeName, valueLength, sourceArray){
if(!this.shaderAttributes)this.shaderAttributes = [];
this.shaderAttributes.push([attributeName, valueLength, sourceArray]);
},
/**
* Description
* @param {} uniformName
* @param {} uniformType
* @param {} object
* @param {} args
*/
addShaderUniform: function(uniformName, uniformType, object, args){
if(!this.shaderUniforms)this.shaderUniforms = [];
this.shaderUniforms.push([uniformName, uniformType, object, args]);
}
};