|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Canvas3D.Mesh = function() { |
|
|
|
this._oPosition = new Canvas3D.Vec3(0,0,0); |
|
this._oRotation = new Canvas3D.Vec3(0,0,0); |
|
|
|
this._aVertices = []; |
|
this._aGlobalVertices = []; |
|
this._aFaces = []; |
|
this._aNormals = []; |
|
this._aMaterials = []; |
|
|
|
this._bDirty = true; |
|
|
|
this._bVisible = true; |
|
|
|
this._iForcedZ = -1; |
|
this._bHideWhenRotating = false; |
|
|
|
this._oDefaultColor = {r:155,g:155,b:155}; |
|
this._oDefaultMaterial = {}; |
|
this._iSize = 1; |
|
|
|
this._fScale = 1; |
|
|
|
this._bFill = true; |
|
this._bWire = false; |
|
this._bShading = true; |
|
this._bBackfaceCull = true; |
|
this._bZSort = true; |
|
this._bExpandClipPath = true; |
|
|
|
this._bTexture = false; |
|
this._bTextureShading = false; |
|
|
|
|
|
|
|
this._bCalcNormals = true; |
|
|
|
|
|
var oCanvas = document.createElement("canvas"); |
|
this._bCanTexture = false; |
|
this._bCanTextureUV = false; |
|
if (oCanvas.getContext && oCanvas.getContext("2d")) { |
|
this._bCanTexture = true; |
|
if (oCanvas.getContext("2d").getImageData) { |
|
this._bCanTextureUV = true; |
|
} |
|
} |
|
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
Canvas3D.Mesh.prototype.setMeshData = function(oMeshData, oScene) { |
|
this._oMeshData = oMeshData; |
|
|
|
this._aVertices = []; |
|
this._aFaces = []; |
|
this._aNormals = []; |
|
this._aMaterials = []; |
|
|
|
var oPos = this._oPosition; |
|
|
|
var me = this; |
|
|
|
if (this._oMeshData.mat) { |
|
for (var m=0;m<this._oMeshData.mat.length;m++) { |
|
var oMat = this._oMeshData.mat[m]; |
|
oMat.idx = m; |
|
if (oMat.t) { |
|
oMat.image = new Image(); |
|
if (oMat.uv && this._bCanTextureUV) { |
|
oMat.image.mat = oMat; |
|
oMat.image.onload = function() { |
|
me._bakeTexture(this.mat); |
|
if (oScene) { |
|
oScene.setDirty(true); |
|
} |
|
this.onload = null; |
|
} |
|
} |
|
oMat.image.src = "textures/" + oMat.t; |
|
} |
|
this._aMaterials.push(oMat); |
|
} |
|
} |
|
|
|
for (var o=0;o<this._oMeshData.obj.length;o++) { |
|
|
|
var oObject = this._oMeshData.obj[o]; |
|
var aVertices = oObject.vrt; |
|
var aTexCoords = oObject.tex; |
|
|
|
this._aTexCoords = aTexCoords; |
|
|
|
var iVertOffset = this._aVertices.length; |
|
|
|
var fTotalX = 0; |
|
var fTotalY = 0; |
|
var fTotalZ = 0; |
|
|
|
var iNumVertices = aVertices.length; |
|
|
|
for (var v=0;v<iNumVertices;v++) { |
|
var oVertex = new Canvas3D.Vec3( |
|
aVertices[v][0], |
|
aVertices[v][1], |
|
aVertices[v][2] |
|
); |
|
|
|
this._aVertices.push(oVertex); |
|
|
|
this._aGlobalVertices.push( |
|
new Canvas3D.Vec3( |
|
oVertex.x + oPos.x, |
|
oVertex.y + oPos.y, |
|
oVertex.z + oPos.z |
|
) |
|
); |
|
|
|
fTotalX += oVertex.x; |
|
fTotalY += oVertex.y; |
|
fTotalZ += oVertex.z; |
|
} |
|
|
|
var fAvgX = fTotalX / iNumVertices; |
|
var fAvgY = fTotalY / iNumVertices; |
|
var fAvgZ = fTotalZ / iNumVertices; |
|
|
|
var oLocalCenter = new Canvas3D.Vec3(fAvgX, fAvgY, fAvgZ); |
|
|
|
var aFaces = oObject.fac; |
|
for (var f=0;f<aFaces.length;f++) { |
|
var oFace = aFaces[f]; |
|
|
|
var oPoint1 = this._aGlobalVertices[oFace[0] + iVertOffset]; |
|
var oPoint2 = this._aGlobalVertices[oFace[1] + iVertOffset]; |
|
var oPoint3 = this._aGlobalVertices[oFace[2] + iVertOffset]; |
|
|
|
var oCenter = new Canvas3D.Vec3( |
|
(oPoint1.x + oPoint2.x + oPoint3.x) / 3, |
|
(oPoint1.y + oPoint2.y + oPoint3.y) / 3, |
|
(oPoint1.z + oPoint2.z + oPoint3.z) / 3 |
|
); |
|
|
|
var oNormal = new Canvas3D.Vec3( |
|
oObject.nrm[f][0], |
|
oObject.nrm[f][1], |
|
oObject.nrm[f][2] |
|
); |
|
|
|
var oFace = { |
|
a : oFace[0] + iVertOffset, |
|
b : oFace[1] + iVertOffset, |
|
c : oFace[2] + iVertOffset, |
|
normal : oNormal, |
|
center : oCenter, |
|
mat : oFace[3], |
|
idx : f, |
|
lights : [] |
|
} |
|
|
|
this._aFaces.push(oFace); |
|
} |
|
|
|
if (this._bCalcNormals) { |
|
this._recalcNormals(); |
|
} |
|
} |
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Canvas3D.Mesh.prototype._bakeTexture = function(oMat) { |
|
|
|
var f = this._aFaces.length; |
|
|
|
var aTexFaces = []; |
|
|
|
do { |
|
var oFace = this._aFaces[f-1]; |
|
if (oFace.mat == oMat.idx) { |
|
aTexFaces.push(oFace); |
|
oFace.texidx = aTexFaces.length-1; |
|
} |
|
} while (--f) |
|
|
|
f = aTexFaces.length; |
|
if (f < 1) { |
|
return; |
|
} |
|
|
|
var fc = aTexFaces.length; |
|
|
|
var iTexRes = oMat.res; |
|
var iTexWidth = iTexRes * f + f*2; |
|
var iTexHeight = iTexRes + 2; |
|
|
|
var iSrcWidth = oMat.w; |
|
var iSrcHeight = oMat.h; |
|
|
|
|
|
var oSource = document.createElement("canvas"); |
|
oSource.width = iSrcWidth; |
|
oSource.height = iSrcHeight; |
|
oSource.style.width = iSrcWidth+"px"; |
|
oSource.style.height = iSrcHeight+"px"; |
|
var oSrcCtx = oSource.getContext("2d"); |
|
oSrcCtx.drawImage(oMat.image, 0, 0, iSrcWidth, iSrcHeight); |
|
var oSrcDataObj = oSrcCtx.getImageData(0, 0, iSrcWidth, iSrcHeight); |
|
var aSrcData = oSrcDataObj.data; |
|
|
|
|
|
var oTexCanvas = document.createElement("canvas"); |
|
oTexCanvas.width = iTexWidth; |
|
oTexCanvas.height = iTexHeight; |
|
oTexCanvas.style.width = iTexWidth+"px"; |
|
oTexCanvas.style.height = (iTexHeight)+"px"; |
|
oTexCanvas.style.backgroundColor = "rgb(255,0,255)"; |
|
oTexCanvas.resolution = iTexRes; |
|
var oDstCtx = oTexCanvas.getContext("2d"); |
|
oDstCtx.fillStyle = "rgb(255,0,255)"; |
|
oDstCtx.fillRect(0,0,iTexWidth,iTexHeight); |
|
|
|
var oDstDataObj = oDstCtx.getImageData(0, 0, iTexWidth, iTexHeight); |
|
var aDstData = oDstDataObj.data; |
|
|
|
var oContext = oTexCanvas.getContext("2d"); |
|
|
|
|
|
|
|
|
|
|
|
var iTexOffsetX = iTexRes; |
|
|
|
do { |
|
var oFace = aTexFaces[f-1]; |
|
|
|
var oCoords = this._aTexCoords[oFace.idx]; |
|
|
|
var oTexPoint1 = oCoords[1]; |
|
var oTexPoint2 = oCoords[2]; |
|
var oTexPoint3 = oCoords[0]; |
|
|
|
var x1 = oTexPoint1[0] * iSrcWidth; |
|
var y1 = (1 - oTexPoint1[1]) * iSrcHeight; |
|
var x3 = oTexPoint2[0] * iSrcWidth; |
|
var y3 = (1 - oTexPoint2[1]) * iSrcHeight; |
|
var x2 = oTexPoint3[0] * iSrcWidth; |
|
var y2 = (1 - oTexPoint3[1]) * iSrcHeight; |
|
|
|
var fUnitAX = (x2 - x1); |
|
var fUnitAY = (y2 - y1); |
|
|
|
var fUnitBX = (x3 - x2); |
|
var fUnitBY = (y3 - y2); |
|
|
|
var iOffsetX = 0; |
|
|
|
var iDstXOffset = (iTexWidth - iTexOffsetX - (fc-f)*2-2); |
|
|
|
|
|
|
|
|
|
var y = iTexRes+2; |
|
do { |
|
var iDstY = iTexRes+2-y; |
|
var fStepY = (iTexRes+1-y) / iTexRes; |
|
|
|
var fStepYUnitBX = fStepY*fUnitBX; |
|
var fStepYUnitBY = fStepY*fUnitBY; |
|
|
|
var iDstYOffset = iDstY*iTexWidth*4; |
|
|
|
var x = iTexRes+2 - iOffsetX; |
|
do { |
|
var iDstX = x + iDstXOffset - 1; |
|
var fStepX = (x-1 + iOffsetX) / iTexRes; |
|
|
|
var iSrcX = Math.floor(x1 + fStepX*fUnitAX + fStepYUnitBX); |
|
var iSrcY = Math.floor(y1 + fStepX*fUnitAY + fStepYUnitBY); |
|
|
|
if (iSrcX < 0) iSrcX = 0; |
|
if (iSrcY < 0) iSrcY = 0; |
|
|
|
if (iSrcX >= iSrcWidth) iSrcX = iSrcWidth-1; |
|
if (iSrcY >= iSrcHeight) iSrcY = iSrcHeight-1; |
|
|
|
var iDstPixOffset = iDstYOffset + iDstX*4; |
|
var iSrcPixOffset = (iSrcY*iSrcWidth + iSrcX)*4; |
|
|
|
aDstData[iDstPixOffset] = aSrcData[iSrcPixOffset]; |
|
aDstData[iDstPixOffset+1] = aSrcData[iSrcPixOffset+1]; |
|
aDstData[iDstPixOffset+2] = aSrcData[iSrcPixOffset+2]; |
|
|
|
aDstData[iDstPixOffset+3] = oMat.texalpha ? aSrcData[iSrcPixOffset+3] : 255; |
|
|
|
} while (--x); |
|
|
|
iOffsetX++; |
|
iDstXOffset++; |
|
|
|
} while (--y); |
|
|
|
iTexOffsetX += iTexRes; |
|
|
|
} while (--f); |
|
|
|
oDstCtx.putImageData(oDstDataObj, 0, 0); |
|
oDstCtx.fillRect(0,0,0,0); |
|
oMat.facecanvas = oTexCanvas; |
|
} |
|
|
|
var fncZSort = function(a, b) { |
|
return a.transcenter.z - b.transcenter.z; |
|
} |
|
|
|
|
|
var sin = Math.sin; |
|
var cos = Math.cos; |
|
var asin = Math.asin; |
|
var acos = Math.acos; |
|
var pow = Math.pow; |
|
var sqrt = Math.sqrt; |
|
|
|
var fRadDeg = 180 / Math.PI; |
|
var fDegRad = Math.PI / 180; |
|
var fDegRad45 = fDegRad*45; |
|
var fDegRad90 = fDegRad*90; |
|
var fDegRad180 = fDegRad*180; |
|
var fSqrt2Div2 = sqrt(2) / 2; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Canvas3D.Mesh.prototype._drawTextureTriangle = function(oContext, oMat, oPoint1, oPoint2, oPoint3, iOffsetX, iOffsetY, fShade, oNormal, iIdx) { |
|
if (!oMat.image) { |
|
return; |
|
} |
|
if (!oMat.image.complete) { |
|
return; |
|
} |
|
|
|
var oMatImage = oMat.image; |
|
|
|
if (!oMatImage.canvas) { |
|
|
|
|
|
|
|
|
|
var iTexWidth = 50; |
|
var iTexHeight = 50; |
|
|
|
var oTextureCanvas = document.createElement("canvas"); |
|
|
|
oTextureCanvas.width = iTexWidth; |
|
oTextureCanvas.height = iTexHeight; |
|
|
|
oTextureCanvas.style.width = iTexWidth + "px"; |
|
oTextureCanvas.style.height = iTexHeight + "px"; |
|
|
|
var oTexCtx = oTextureCanvas.getContext("2d"); |
|
oTexCtx.drawImage(oMatImage, 0, 0, iTexWidth, iTexHeight); |
|
|
|
oMatImage.canvas = oTextureCanvas; |
|
} |
|
|
|
var x1 = oPoint1.x; |
|
var y1 = oPoint1.y; |
|
var x2 = oPoint2.x; |
|
var y2 = oPoint2.y; |
|
var x3 = oPoint3.x; |
|
var y3 = oPoint3.y; |
|
|
|
|
|
var dx = x3 - x2; |
|
var dy = y3 - y2; |
|
var a = sqrt((dx*dx + dy*dy)); |
|
|
|
dx = x3 - x1; |
|
dy = y3 - y1; |
|
var b = sqrt((dx*dx + dy*dy)); |
|
|
|
dx = x2 - x1; |
|
dy = y2 - y1; |
|
var c = sqrt((dx*dx + dy*dy)); |
|
|
|
var aa = a*a, bb = b*b, cc = c*c; |
|
|
|
var fCosB = (aa + cc - bb) / (2*a*c); |
|
var fAngleB = acos(fCosB); |
|
if (isNaN(fAngleB)) return; |
|
|
|
var fCosC = (aa + bb - cc) / (2*a*b); |
|
var fAngleC = acos(fCosC); |
|
if (isNaN(fAngleC)) return; |
|
|
|
if ((fAngleB + fAngleC) == 0) return; |
|
|
|
var fSkewX = -(fDegRad90 - (fAngleB + fAngleC)); |
|
|
|
var fTriRotation = -(asin((y2 - y1) / c)); |
|
|
|
if (x2 > x1) { |
|
fTriRotation = fDegRad180 - fTriRotation; |
|
} |
|
|
|
if (fSkewX == fDegRad90) fSkewX = fDegRad*89.99; |
|
if (fSkewX == -fDegRad90) fSkewX = -fDegRad*89.99; |
|
|
|
var fCosX = cos(fSkewX); |
|
|
|
var fRotation = fDegRad45 + fSkewX * 0.5; |
|
|
|
var fDiv = 1 / (sin(fRotation) * fSqrt2Div2); |
|
|
|
var fScaleX = fCosX * fDiv; |
|
var fScaleY = (sin(fSkewX) + 1) * fDiv; |
|
|
|
|
|
var iClipX1 = x1 + iOffsetX; |
|
var iClipY1 = y1 + iOffsetY; |
|
|
|
var iClipX2 = x2 + iOffsetX; |
|
var iClipY2 = y2 + iOffsetY; |
|
|
|
var iClipX3 = x3 + iOffsetX; |
|
var iClipY3 = y3 + iOffsetY; |
|
|
|
|
|
|
|
|
|
|
|
if (this._bExpandClipPath && false) { |
|
if (iClipY1 < iClipY2 && iClipY1 < iClipY3) |
|
iClipY1--; |
|
else if (iClipY2 < iClipY1 && iClipY2 < iClipY3) |
|
iClipY2--; |
|
else if (iClipY3 < iClipY1 && iClipY3 < iClipY2) |
|
iClipY3--; |
|
|
|
if (iClipY1 > iClipY2 && iClipY1 > iClipY3) |
|
iClipY1++; |
|
else if (iClipY2 > iClipY1 && iClipY2 > iClipY3) |
|
iClipY2++; |
|
else if (iClipY3 > iClipY1 && iClipY3 > iClipY2) |
|
iClipY3++; |
|
|
|
if (iClipX1 < iClipX2 && iClipX1 < iClipX3) |
|
iClipX1--; |
|
else if (iClipX2 < iClipX1 && iClipX2 < iClipX3) |
|
iClipX2--; |
|
else if (iClipX3 < iClipX1 && iClipX3 < iClipX2) |
|
iClipX3--; |
|
|
|
if (iClipX1 > iClipX2 && iClipX1 > iClipX3) |
|
iClipX1++; |
|
else if (iClipX2 > iClipX1 && iClipX2 > iClipX3) |
|
iClipX2++; |
|
else if (iClipX3 > iClipX1 && iClipX3 > iClipX2) |
|
iClipX3++; |
|
} |
|
|
|
oContext.save(); |
|
|
|
|
|
oContext.beginPath(); |
|
oContext.moveTo(iClipX1, iClipY1); |
|
oContext.lineTo(iClipX2, iClipY2); |
|
oContext.lineTo(iClipX3, iClipY3); |
|
oContext.closePath(); |
|
oContext.clip(); |
|
|
|
|
|
oContext.translate(x2 + iOffsetX, y2 + iOffsetY); |
|
oContext.rotate(fRotation + fTriRotation); |
|
oContext.scale(fScaleX, fScaleY); |
|
oContext.rotate(-fDegRad45); |
|
|
|
var fTriScaleX = c / 2; |
|
var fTriScaleY = b / 2; |
|
|
|
if (oMat.uv) { |
|
|
|
if (this._bCanTextureUV && oMat.facecanvas) { |
|
var iTexRes = oMat.facecanvas.resolution; |
|
|
|
|
|
oContext.drawImage( |
|
oMat.facecanvas, |
|
iIdx * iTexRes + iIdx*2+1, 1, iTexRes, iTexRes, |
|
-1, -1, |
|
fTriScaleX + 2, |
|
fTriScaleY + 2 |
|
); |
|
} |
|
} else { |
|
|
|
oContext.drawImage( |
|
oMatImage.canvas, |
|
-1, -1, |
|
fTriScaleX + 2, |
|
fTriScaleY + 2 |
|
); |
|
} |
|
|
|
oContext.restore(); |
|
|
|
|
|
|
|
|
|
if (this._bTextureShading && fShade > 0) { |
|
oContext.beginPath(); |
|
oContext.moveTo(iClipX1, iClipY1); |
|
oContext.lineTo(iClipX2, iClipY2); |
|
oContext.lineTo(iClipX3, iClipY3); |
|
oContext.closePath(); |
|
|
|
oContext.fillStyle = "rgba(0,0,0," + (fShade*0.5) + ")"; |
|
oContext.fill(); |
|
} |
|
} |
|
|
|
|
|
Canvas3D.Mesh.prototype.draw = function(oContext, iOffsetX, iOffsetY) { |
|
if (!this._bVisible) return; |
|
|
|
var oScene = this._oScene; |
|
|
|
var oCam = oScene.getActiveCamera(); |
|
var oAmbient = oScene.getAmbientLight() |
|
|
|
|
|
var bLightDirty = false; |
|
if (this._bShading && this._bFill) { |
|
var aLights = oScene.getLights(); |
|
var aLightDirections = []; |
|
for (var l=0;l<aLights.length;l++) { |
|
|
|
var oLightPos = aLights[l].getPosition(); |
|
var oLightDirection = oLightPos.unit(); |
|
aLightDirections.push(oLightDirection); |
|
|
|
if (aLights[l].getDirty()) |
|
bLightDirty = true; |
|
} |
|
} |
|
|
|
var aVertices = this._aGlobalVertices; |
|
var aFaces = this._aFaces; |
|
|
|
if (aVertices.length < 3 || aFaces.length < 1) { |
|
|
|
return; |
|
} |
|
|
|
|
|
var aPoints2D = []; |
|
var aTransVertices = []; |
|
var v = aVertices.length; |
|
do { |
|
var oVertex = aVertices[v-1]; |
|
|
|
var oVec = oCam.transformPoint(oVertex); |
|
aTransVertices[v-1] = oVec; |
|
|
|
var oPoint2D = oCam.project(oVec); |
|
aPoints2D[v-1] = oPoint2D; |
|
} while (--v); |
|
|
|
var aSortedFaces; |
|
|
|
|
|
if (this._bFill && this._bZSort) { |
|
var f = aFaces.length; |
|
do { |
|
var oFace = aFaces[f-1]; |
|
oFace.transcenter = oCam.transformPoint(oFace.center); |
|
} while (--f); |
|
|
|
aSortedFaces = aFaces.sort(fncZSort); |
|
|
|
|
|
} else { |
|
|
|
aSortedFaces = aFaces; |
|
} |
|
|
|
f = aSortedFaces.length; |
|
if (f < 1) { |
|
return; |
|
} |
|
|
|
|
|
do { |
|
var oFace = aSortedFaces[f-1]; |
|
|
|
var oPoint1 = aPoints2D[oFace.a]; |
|
var oPoint2 = aPoints2D[oFace.b]; |
|
var oPoint3 = aPoints2D[oFace.c]; |
|
|
|
var oNormal = oFace.normal; |
|
|
|
var bDraw = false; |
|
|
|
|
|
if (this._bBackfaceCull) { |
|
|
|
if (((oPoint3.y-oPoint1.y)/(oPoint3.x-oPoint1.x) - (oPoint2.y-oPoint1.y)/(oPoint2.x-oPoint1.x) <= 0) ^ (oPoint1.x <= oPoint3.x == oPoint1.x > oPoint2.x)){ |
|
bDraw = true; |
|
} |
|
} else { |
|
bDraw = true; |
|
} |
|
|
|
if (oCam.clip(aTransVertices[oFace.a]) || oCam.clip(aTransVertices[oFace.b]) || oCam.clip(aTransVertices[oFace.c])) { |
|
bDraw = false; |
|
} |
|
|
|
|
|
|
|
if (bDraw) { |
|
|
|
|
|
var oFaceMat = this._aMaterials[oFace.mat]; |
|
if (oFaceMat) { |
|
oFaceColor = oFaceMat; |
|
} else { |
|
oFaceMat = this._oDefaultMaterial; |
|
oFaceColor = this._oDefaultColor; |
|
} |
|
var bFaceTexture = this._bTexture && oFaceMat.t; |
|
|
|
|
|
var oFaceOrgColor = {r:oFaceColor.r, g:oFaceColor.g, b:oFaceColor.b}; |
|
|
|
var fLight = 0; |
|
var fShade = 1; |
|
|
|
if (this._bFill) { |
|
|
|
if (!bFaceTexture) { |
|
if (bLightDirty || this._bDirty) { |
|
var oFaceColorAmb = { |
|
r:(oAmbient.r / 255) * oFaceColor.r, |
|
g:(oAmbient.g / 255) * oFaceColor.g, |
|
b:(oAmbient.b / 255) * oFaceColor.b |
|
}; |
|
} |
|
} |
|
|
|
|
|
if (this._bShading) { |
|
if (bLightDirty || this._bDirty) { |
|
for (var l=0;l<aLights.length;l++) { |
|
|
|
var oLightPos = aLights[l].getPosition(); |
|
var oLightDir = new Canvas3D.Vec3( |
|
oLightPos.x - oFace.center.x, |
|
oLightPos.y - oFace.center.y, |
|
oLightPos.z - oFace.center.z |
|
).unit(); |
|
|
|
var fDot = -oLightDir.dot(oNormal); |
|
|
|
|
|
if (fDot > 0) { |
|
|
|
fLight = fDot * aLights[l].getIntensity(); |
|
fShade = fShade - fLight; |
|
|
|
|
|
if (!bFaceTexture) { |
|
oFaceColorAmb = { |
|
r: oFaceColorAmb.r + oFaceColor.r * fLight, |
|
g: oFaceColorAmb.g + oFaceColor.g * fLight, |
|
b: oFaceColorAmb.b + oFaceColor.b * fLight |
|
}; |
|
} |
|
} |
|
} |
|
|
|
oFaceColorAmb.r = Math.floor(oFaceColorAmb.r); |
|
oFaceColorAmb.g = Math.floor(oFaceColorAmb.g); |
|
oFaceColorAmb.b = Math.floor(oFaceColorAmb.b); |
|
|
|
if (oFaceColorAmb.r < 0) oFaceColorAmb.r = 0; |
|
if (oFaceColorAmb.g < 0) oFaceColorAmb.g = 0; |
|
if (oFaceColorAmb.b < 0) oFaceColorAmb.b = 0; |
|
|
|
if (oFaceColorAmb.r > 255) oFaceColorAmb.r = 255; |
|
if (oFaceColorAmb.g > 255) oFaceColorAmb.g = 255; |
|
if (oFaceColorAmb.b > 255) oFaceColorAmb.b = 255; |
|
|
|
oFace.calccolor = oFaceColorAmb; |
|
oFace.shade = fShade; |
|
} |
|
oFaceColorAmb = oFace.calccolor; |
|
fShade = oFace.shade; |
|
} |
|
if (!bFaceTexture) { |
|
oFaceColor = oFaceColorAmb; |
|
} |
|
} |
|
|
|
oContext.beginPath(); |
|
oContext.moveTo(oPoint1.x + iOffsetX, oPoint1.y + iOffsetY); |
|
oContext.lineTo(oPoint2.x + iOffsetX, oPoint2.y + iOffsetY) |
|
oContext.lineTo(oPoint3.x + iOffsetX, oPoint3.y + iOffsetY) |
|
oContext.closePath(); |
|
|
|
if (this._bFill) { |
|
if (this._bCanTexture && this._bTexture && oFaceMat.image) { |
|
this._drawTextureTriangle(oContext, oFaceMat, oPoint1, oPoint2, oPoint3, iOffsetX, iOffsetY, fShade, oNormal, oFace.texidx); |
|
} else { |
|
oContext.fillStyle = "rgb(" + oFaceColor.r + "," + oFaceColor.g + "," + oFaceColor.b + ")"; |
|
oContext.fill(); |
|
if (!this._bWire) { |
|
oContext.lineWidth = 0.7; |
|
oContext.strokeStyle = "rgb(" + oFaceColor.r + "," + oFaceColor.g + "," + oFaceColor.b + ")"; |
|
oContext.stroke(); |
|
} |
|
} |
|
} |
|
|
|
if (this._bWire) { |
|
oFaceOrgColor.r = Math.min(Math.max(Math.round(oFaceOrgColor.r),0),255); |
|
oFaceOrgColor.g = Math.min(Math.max(Math.round(oFaceOrgColor.g),0),255); |
|
oFaceOrgColor.b = Math.min(Math.max(Math.round(oFaceOrgColor.b),0),255); |
|
|
|
oContext.lineWidth = 1; |
|
oContext.strokeStyle = "rgb(" + oFaceOrgColor.r + "," + oFaceOrgColor.g + "," + oFaceOrgColor.b + ")"; |
|
oContext.stroke(); |
|
} |
|
|
|
} |
|
} while (--f); |
|
this._bDirty = false; |
|
} |
|
|
|
Canvas3D.Mesh.prototype.setScene = function(oScene) { |
|
if (this._oScene != oScene) { |
|
this._oScene = oScene; |
|
} |
|
} |
|
|
|
Canvas3D.Mesh.prototype.setLighting = function(bEnable) { |
|
this._bShading = bEnable; |
|
} |
|
|
|
Canvas3D.Mesh.prototype.setBackfaceCull = function(bEnable) { |
|
this._bBackfaceCull = bEnable; |
|
} |
|
|
|
Canvas3D.Mesh.prototype.setZSort = function(bEnable) { |
|
this._bZSort = bEnable; |
|
} |
|
|
|
Canvas3D.Mesh.prototype.setFill = function(bEnable) { |
|
this._bFill = bEnable; |
|
} |
|
|
|
Canvas3D.Mesh.prototype.setWire = function(bEnable) { |
|
this._bWire = bEnable; |
|
} |
|
|
|
Canvas3D.Mesh.prototype.setTexture = function(bEnable) { |
|
this._bTexture = bEnable; |
|
} |
|
|
|
Canvas3D.Mesh.prototype.setTextureShading = function(bEnable) { |
|
this._bTextureShading = bEnable; |
|
} |
|
|
|
Canvas3D.Mesh.prototype._updateGlobalVertices = function() { |
|
var oRot = this._oRotation; |
|
var oPos = this._oPosition; |
|
|
|
for (var i = 0; i < this._aVertices.length; i++) { |
|
var oRotatedVertex = new Canvas3D.Vec3( |
|
this._aVertices[i].x, |
|
this._aVertices[i].y, |
|
this._aVertices[i].z |
|
); |
|
|
|
if (oRot.x) |
|
oRotatedVertex.rotateX(oRot.x); |
|
if (oRot.y) |
|
oRotatedVertex.rotateY(oRot.y); |
|
if (oRot.z) |
|
oRotatedVertex.rotateZ(oRot.z); |
|
|
|
this._aGlobalVertices[i].x = oRotatedVertex.x * this._fScale + oPos.x; |
|
this._aGlobalVertices[i].y = oRotatedVertex.y * this._fScale + oPos.y; |
|
this._aGlobalVertices[i].z = oRotatedVertex.z * this._fScale + oPos.z; |
|
} |
|
|
|
this._recalcNormals(); |
|
} |
|
|
|
Canvas3D.Mesh.prototype._recalcNormals = function() { |
|
for (var f = 0; f < this._aFaces.length; f++) { |
|
var oFace = this._aFaces[f]; |
|
|
|
var oPoint1 = this._aGlobalVertices[oFace.a]; |
|
var oPoint2 = this._aGlobalVertices[oFace.b]; |
|
var oPoint3 = this._aGlobalVertices[oFace.c]; |
|
|
|
var oCenter = new Canvas3D.Vec3( |
|
(oPoint1.x + oPoint2.x + oPoint3.x) / 3, |
|
(oPoint1.y + oPoint2.y + oPoint3.y) / 3, |
|
(oPoint1.z + oPoint2.z + oPoint3.z) / 3 |
|
); |
|
|
|
oFace.center = oCenter; |
|
|
|
var oNormal = new Canvas3D.Vec3( |
|
((oPoint1.y - oPoint2.y) * (oPoint1.z - oPoint3.z)) - ((oPoint1.z - oPoint2.z) * (oPoint1.y - oPoint3.y)), |
|
((oPoint1.z - oPoint2.z) * (oPoint1.x - oPoint3.x)) - ((oPoint1.x - oPoint2.x) * (oPoint1.z - oPoint3.z)), |
|
((oPoint1.x - oPoint2.x) * (oPoint1.y - oPoint3.y)) - ((oPoint1.y - oPoint2.y) * (oPoint1.x - oPoint3.x)) |
|
).unit(); |
|
oFace.normal = oNormal; |
|
} |
|
} |
|
|
|
Canvas3D.Mesh.prototype.setPosition = function(oVec) { |
|
if (oVec.x != this._oPosition.x || oVec.y != this._oPosition.y || oVec.z != this._oPosition.z) { |
|
this._oPosition = oVec; |
|
this._updateGlobalVertices(); |
|
this._bDirty = true; |
|
} |
|
} |
|
|
|
Canvas3D.Mesh.prototype.setRotation = function(oVec) { |
|
this._oRotation = oVec; |
|
this._updateGlobalVertices(); |
|
|
|
this._bDirty = true; |
|
|
|
} |
|
|
|
Canvas3D.Mesh.prototype.getPosition = function(oVec) { |
|
return this._oPosition; |
|
} |
|
|
|
Canvas3D.Mesh.prototype.setForcedZ = function(iZ) { |
|
this._iForcedZ = iZ; |
|
} |
|
|
|
Canvas3D.Mesh.prototype.getForcedZ = function() { |
|
return this._iForcedZ; |
|
} |
|
|
|
Canvas3D.Mesh.prototype.getHideWhenRotating = function() { |
|
return this._bHideWhenRotating; |
|
} |
|
|
|
Canvas3D.Mesh.prototype.setHideWhenRotating = function(bEnable) { |
|
this._bHideWhenRotating = bEnable; |
|
} |
|
|
|
Canvas3D.Mesh.prototype.getDirty = function() { |
|
return this._bDirty; |
|
} |
|
|
|
Canvas3D.Mesh.prototype.hide = function() { |
|
this._bVisible = false; |
|
this._bDirty = true; |
|
} |
|
|
|
Canvas3D.Mesh.prototype.show = function() { |
|
this._bVisible = true; |
|
this._bDirty = true; |
|
} |
|
|
|
Canvas3D.Mesh.prototype.isVisible = function() { |
|
return this._bVisible; |
|
} |
|
|
|
Canvas3D.Mesh.prototype.setScale = function(fScale) { |
|
this._fScale = fScale; |
|
this._bDirty = true; |
|
this._updateGlobalVertices(); |
|
} |
|
|
|
Canvas3D.Mesh.prototype.getScale = function() { |
|
return this._fScale; |
|
} |
|
|