|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Canvas3D.Camera = function() { |
|
|
|
this._oPosition = new Canvas3D.Vec3(0,0,0); |
|
|
|
this._oSideVec = new Canvas3D.Vec3(1,0,0); |
|
this._oUpVec = new Canvas3D.Vec3(0,1,0); |
|
this._oOutVec = new Canvas3D.Vec3(0,0,1); |
|
|
|
this._oRotMat = new Canvas3D.Matrix3(); |
|
|
|
this._bDirty = false; |
|
this._fFocal = 500; |
|
this._fFocalDistance = this._fFocal; |
|
|
|
this._bReverseX = false; |
|
this._bReverseY = false; |
|
|
|
this._bTarget = true; |
|
|
|
this._iClipNear = 1; |
|
this._iClipFar = 10000000; |
|
|
|
this._fScale = 1; |
|
|
|
this._oLookAt = new Canvas3D.Vec3(0,0,0); |
|
|
|
}; |
|
|
|
var proto = Canvas3D.Camera.prototype; |
|
|
|
proto.getDirty = function() { |
|
return this._bDirty; |
|
} |
|
|
|
proto.setDirty = function(bDirty) { |
|
this._bDirty = bDirty; |
|
} |
|
|
|
proto.setPosition = function(oPos) { |
|
this._oPosition.set(oPos.x, oPos.y, oPos.z); |
|
this._bDirty = true; |
|
} |
|
|
|
proto.getPosition = function() { |
|
return this._oPosition; |
|
} |
|
|
|
proto.setScale = function(fScale) { |
|
this._fScale = fScale; |
|
this._bDirty = true; |
|
} |
|
|
|
proto.getScale = function() { |
|
return this._fScale; |
|
} |
|
|
|
proto.getSide = function() { |
|
return this._oSideVec; |
|
} |
|
|
|
proto.getUp = function() { |
|
return this._oUpVec; |
|
} |
|
|
|
proto.setUp = function(oVec) { |
|
this._oUpVec = oVec; |
|
} |
|
|
|
proto.getOut = function() { |
|
return this._oOutVec; |
|
} |
|
|
|
proto.moveSideways = function(d) { |
|
this._oPosition.x += this._oSideVec.x * d; |
|
this._oPosition.y += this._oSideVec.y * d; |
|
this._oPosition.z += this._oSideVec.z * d; |
|
this.setDirty(true); |
|
} |
|
|
|
proto.moveUpwards = function(d) { |
|
this._oPosition.x += this._oUpVec.x * d; |
|
this._oPosition.y += this._oUpVec.y * d; |
|
this._oPosition.z += this._oUpVec.z * d; |
|
this.setDirty(true); |
|
} |
|
|
|
proto.moveForward = function(d) { |
|
this._oPosition.x += this._oOutVec.x * d; |
|
this._oPosition.y += this._oOutVec.y * d; |
|
this._oPosition.z += this._oOutVec.z * d; |
|
this.setDirty(true); |
|
} |
|
|
|
|
|
proto.pitchAroundTarget = function(fTheta, oTarget) { |
|
var M = new Canvas3D.Matrix3(); |
|
var oPos = this.getPosition(); |
|
oTarget = oTarget || this.getLookAt(); |
|
|
|
|
|
oPos.subVector(oTarget); |
|
|
|
|
|
M.loadRotationAxis(this._oSideVec, Math.sin(fTheta * Math.PI / 180.0), Math.cos(fTheta * Math.PI / 180.0)); |
|
oPos = M.multiplyVector(oPos); |
|
|
|
|
|
oPos.addVector(oTarget); |
|
|
|
this.setPosition(oPos); |
|
this.setDirty(true); |
|
} |
|
|
|
proto.yaw = function(fTheta) { |
|
var M = new Canvas3D.Matrix3(); |
|
M.loadRotationAxis(this._oUpVec, Math.sin(fTheta), Math.cos(fTheta)); |
|
this._oSideVec = M.multiplyVector(this._oSideVec); |
|
this._oOutVec = M.multiplyVector(this._oOutVec); |
|
this.setDirty(true); |
|
} |
|
|
|
|
|
proto.yawAroundTarget = function(fTheta, oTarget) { |
|
var M = new Canvas3D.Matrix3(); |
|
var oPos = this.getPosition(); |
|
oTarget = oTarget || this.getLookAt(); |
|
|
|
|
|
oPos.subVector(oTarget); |
|
|
|
|
|
M.loadRotationAxis(this._oUpVec, Math.sin(fTheta * Math.PI / 180.0), Math.cos(fTheta * Math.PI / 180.0)); |
|
oPos = M.multiplyVector(oPos); |
|
|
|
|
|
oPos.addVector(oTarget); |
|
|
|
this.setPosition(oPos); |
|
this.setDirty(true); |
|
} |
|
|
|
|
|
proto.rollAroundTarget = function(fTheta, oTarget) { |
|
var M = new Canvas3D.Matrix3(); |
|
var oPos = this.getPosition(); |
|
oTarget = oTarget || this.getLookAt(); |
|
|
|
|
|
oPos.subVector(oTarget); |
|
|
|
|
|
M.loadRotationAxis(this._oOutVec, Math.sin(fTheta * Math.PI / 180.0), Math.cos(fTheta * Math.PI / 180.0)); |
|
oPos = M.multiplyVector(oPos); |
|
|
|
|
|
oPos.addVector(oTarget); |
|
|
|
this.setPosition(oPos); |
|
this.setDirty(true); |
|
} |
|
|
|
proto.rotateY = function(sine, cosine) { |
|
var M = new Canvas3D.Matrix3(); |
|
M.loadRotationY(sine, cosine); |
|
this._oSideVec = M.multiplyVector(this._oSideVec); |
|
this._oUpVec = M.multiplyVector(this._oUpVec); |
|
this._oOutVec = M.multiplyVector(this._oOutVec); |
|
this.setDirty(true); |
|
} |
|
|
|
|
|
proto.lookAt = function(P, Up) { |
|
Up = Up || this._oUpVec; |
|
this._oOutVec = P.returnSub(this._oPosition).unit(); |
|
|
|
|
|
|
|
this._oSideVec = this._oOutVec.cross(Up).unit(); |
|
this._oUpVec = this._oSideVec.cross(this._oOutVec).unit(); |
|
this._vecLookAt = P.clone(); |
|
this.setDirty(true); |
|
} |
|
|
|
proto.getLookAt = function() { |
|
return this._vecLookAt; |
|
} |
|
|
|
proto.updateRotationMatrix = function() { |
|
var e0 = this._oRotMat.e[0]; |
|
var e1 = this._oRotMat.e[1]; |
|
var e2 = this._oRotMat.e[2]; |
|
|
|
e0[0] = this._oSideVec.x; |
|
e0[1] = this._oSideVec.y; |
|
e0[2] = this._oSideVec.z; |
|
|
|
e1[0] = this._oUpVec.x; |
|
e1[1] = this._oUpVec.y; |
|
e1[2] = this._oUpVec.z; |
|
|
|
e2[0] = this._oOutVec.x; |
|
e2[1] = this._oOutVec.y; |
|
e2[2] = this._oOutVec.z; |
|
} |
|
|
|
proto.transformPoint = function(P) { |
|
var e = this._oRotMat.e; |
|
var oPos = this._oPosition; |
|
|
|
var e0 = e[0]; |
|
var e1 = e[1]; |
|
var e2 = e[2]; |
|
|
|
var vx = P.x - oPos.x; |
|
var vy = P.y - oPos.y; |
|
var vz = P.z - oPos.z; |
|
|
|
return new Canvas3D.Vec3( |
|
(vx * e0[0] + vy * e0[1] + vz * e0[2]), |
|
(vx * e1[0] + vy * e1[1] + vz * e1[2]), |
|
(vx * e2[0] + vy * e2[1] + vz * e2[2]) |
|
); |
|
} |
|
|
|
proto.project = function(P) { |
|
var fFocal = this._fFocal; |
|
return { |
|
x: P.x * fFocal / (P.z + this._fFocalDistance) * this._fScale * (this._bReverseX?-1:1), |
|
y: -P.y * fFocal / (P.z + this._fFocalDistance) * this._fScale * (this._bReverseY?-1:1) |
|
}; |
|
} |
|
|
|
proto.clip = function(P) { |
|
if (P.z < 0) { |
|
return true; |
|
} |
|
return false; |
|
} |
|
|
|
proto.isBehind = function(P) { |
|
if (P.z > 0) return false; |
|
return false; |
|
} |
|
|
|
proto.getClipNear = function() { |
|
return this._iClipNear; |
|
} |
|
|
|
proto.getClipFar = function() { |
|
return this._iClipFar; |
|
} |
|
|
|
proto.clip = function(P) { |
|
if (P.z > this._iClipNear && P.z < this._iClipFar) { |
|
return false; |
|
} else { |
|
return true; |
|
} |
|
} |
|
|
|
proto.setFOV = function(fFOV) { |
|
this._fFOV = fFOV; |
|
var fFocal = 1 / Math.tan(105 * Math.PI*Math.PI / (180*180 * 2)); |
|
this._fFocal = fFocal; |
|
this._fFocalDistance = fFocal; |
|
} |
|
|
|
proto.getFOV = function() { |
|
return this._fFOV; |
|
} |
|
|
|
proto.getFocal = function() { |
|
return this._fFocal; |
|
} |
|
|
|
proto.setFocalDistance = function(fValue) { |
|
this._fFocalDistance = fValue; |
|
} |
|
|
|
proto.setReverseX = function(bEnable) { |
|
this._bReverseX = bEnable; |
|
} |
|
|
|
proto.setReverseY = function(bEnable) { |
|
this._bReverseY = bEnable; |
|
} |
|
|