diff --git a/src/alternativa/engine3d/loaders/collada/DaeController.as b/src/alternativa/engine3d/loaders/collada/DaeController.as index de76b31..257915a 100644 --- a/src/alternativa/engine3d/loaders/collada/DaeController.as +++ b/src/alternativa/engine3d/loaders/collada/DaeController.as @@ -139,11 +139,10 @@ package alternativa.engine3d.loaders.collada { var data:ByteArray = geometry._vertexStreams[0].data; var numMappings:int = geometry._vertexStreams[0].attributes.length; - // TODO: Need check for existing normals and tangents in model // TODO: Normalize normal and tangent after transformation // TODO: Transform normal with transpose inverted matrix - var normalOffset:uint = geometry.getAttributeOffset(VertexAttributes.NORMAL); - var tangentOffset:uint = geometry.getAttributeOffset(VertexAttributes.TANGENT4); + var normalOffset:int = (geometry.hasAttribute(VertexAttributes.NORMAL))?geometry.getAttributeOffset(VertexAttributes.NORMAL):-1; + var tangentOffset:int = (geometry.hasAttribute(VertexAttributes.TANGENT4))?geometry.getAttributeOffset(VertexAttributes.TANGENT4):-1; for (var i:int = 0; i < geometry._numVertices; i++) { data.position = 4*numMappings*i; @@ -155,25 +154,46 @@ package alternativa.engine3d.loaders.collada { data.writeFloat(x*bindShapeMatrix[4] + y*bindShapeMatrix[5] + z*bindShapeMatrix[6] + bindShapeMatrix[7]); data.writeFloat(x*bindShapeMatrix[8] + y*bindShapeMatrix[9] + z*bindShapeMatrix[10] + bindShapeMatrix[11]); - data.position = 4*(numMappings*i + normalOffset); - var normalX:Number = data.readFloat(); - var normalY:Number = data.readFloat(); - var normalZ:Number = data.readFloat(); - data.position -= 12; + var tmpX:Number; + var tmpY:Number; + var tmpZ:Number; + var tmpLen:Number; - data.writeFloat(normalX*bindShapeMatrix[0] + normalY*bindShapeMatrix[1] + normalZ*bindShapeMatrix[2]); - data.writeFloat(normalX*bindShapeMatrix[4] + normalY*bindShapeMatrix[5] + normalZ*bindShapeMatrix[6]); - data.writeFloat(normalX*bindShapeMatrix[8] + normalY*bindShapeMatrix[9] + normalZ*bindShapeMatrix[10]); + if (normalOffset>=0){ + data.position = 4*(numMappings*i + normalOffset); + var normalX:Number = data.readFloat(); + var normalY:Number = data.readFloat(); + var normalZ:Number = data.readFloat(); - data.position = 4*(numMappings*i + tangentOffset); - var tangentX:Number = data.readFloat(); - var tangentY:Number = data.readFloat(); - var tangentZ:Number = data.readFloat(); - data.position -= 12; - data.writeFloat(tangentX*bindShapeMatrix[0] + tangentY*bindShapeMatrix[1] + tangentZ*bindShapeMatrix[2]); - data.writeFloat(tangentX*bindShapeMatrix[4] + tangentY*bindShapeMatrix[5] + tangentZ*bindShapeMatrix[6]); - data.writeFloat(tangentX*bindShapeMatrix[8] + tangentY*bindShapeMatrix[9] + tangentZ*bindShapeMatrix[10]); + tmpX = normalX*bindShapeMatrix[0] + normalY*bindShapeMatrix[1] + normalZ*bindShapeMatrix[2]; + tmpY = normalX*bindShapeMatrix[4] + normalY*bindShapeMatrix[5] + normalZ*bindShapeMatrix[6]; + tmpZ = normalX*bindShapeMatrix[8] + normalY*bindShapeMatrix[9] + normalZ*bindShapeMatrix[10]; + tmpLen = Math.sqrt(tmpX*tmpX + tmpY*tmpY + tmpZ*tmpZ); + data.position -= 12; + data.writeFloat((tmpLen > 0.0001) ? tmpX/tmpLen : 0); + data.writeFloat((tmpLen > 0.0001) ? tmpY/tmpLen : 0); + data.writeFloat((tmpLen > 0.0001) ? tmpZ/tmpLen : 1); + } + + if (tangentOffset>=0){ + data.position = 4*(numMappings*i + tangentOffset); + var tangentX:Number = data.readFloat(); + var tangentY:Number = data.readFloat(); + var tangentZ:Number = data.readFloat(); + var tangentW:Number = data.readFloat(); + + tmpX = tangentX*bindShapeMatrix[0] + tangentY*bindShapeMatrix[1] + tangentZ*bindShapeMatrix[2]; + tmpY = tangentX*bindShapeMatrix[4] + tangentY*bindShapeMatrix[5] + tangentZ*bindShapeMatrix[6]; + tmpZ = tangentX*bindShapeMatrix[8] + tangentY*bindShapeMatrix[9] + tangentZ*bindShapeMatrix[10]; + tmpLen = Math.sqrt(tmpX*tmpX + tmpY*tmpY + tmpZ*tmpZ); + + data.position -= 16; + data.writeFloat((tmpLen > 0.0001) ? tmpX/tmpLen : 0); + data.writeFloat((tmpLen > 0.0001) ? tmpY/tmpLen : 0); + data.writeFloat((tmpLen > 0.0001) ? tmpZ/tmpLen : 1); + data.writeFloat((tangentW < 0) ? -1 : 1); + } } } diff --git a/src/alternativa/engine3d/materials/StandardMaterial.as b/src/alternativa/engine3d/materials/StandardMaterial.as index 018a952..dc5a8f5 100644 --- a/src/alternativa/engine3d/materials/StandardMaterial.as +++ b/src/alternativa/engine3d/materials/StandardMaterial.as @@ -382,12 +382,10 @@ package alternativa.engine3d.materials { A3DUtils.checkParent(getDefinitionByName(getQualifiedClassName(lightMap)) as Class, resourceType)) { resources[lightMap] = true; } - if (glossinessMap != null && A3DUtils.checkParent(getDefinitionByName(getQualifiedClassName(glossinessMap)) as Class, resourceType)) { resources[glossinessMap] = true; } - if (specularMap != null && A3DUtils.checkParent(getDefinitionByName(getQualifiedClassName(specularMap)) as Class, resourceType)) { resources[specularMap] = true; @@ -775,6 +773,16 @@ package alternativa.engine3d.materials { drawUnit.setFragmentConstantsFromNumbers(program.fragmentShader.getVariableIndex("cSurface"), 0, glossiness, specularPower, 1); drawUnit.setFragmentConstantsFromNumbers(program.fragmentShader.getVariableIndex("cThresholdAlpha"), alphaThreshold, 0, 0, alpha); + var light:Light3D; + var len:Number; + var transform:Transform3D; + var rScale:Number; + var omni:OmniLight; + var spot:SpotLight; + var falloff:Number; + var hotspot:Number; + + if (lightsLength > 0 || shadowedLight) { if (_normalMapSpace == NormalMapSpace.TANGENT_RIGHT_HANDED || _normalMapSpace == NormalMapSpace.TANGENT_LEFT_HANDED) { drawUnit.setVertexBufferAt(program.vertexShader.getVariableIndex("aNormal"), normalsBuffer, geometry._attributesOffsets[VertexAttributes.NORMAL], VertexAttributes.FORMATS[VertexAttributes.NORMAL]); @@ -785,18 +793,16 @@ package alternativa.engine3d.materials { var camTransform:Transform3D = object.cameraToLocalTransform; drawUnit.setVertexConstantsFromNumbers(program.vertexShader.getVariableIndex("cCameraPosition"), camTransform.d, camTransform.h, camTransform.l); - var transform:Transform3D; - var rScale:Number; for (var i:int = 0; i < lightsLength; i++) { - var light:Light3D = lights[i]; + light = lights[i]; if (light is DirectionalLight) { transform = light.lightToObjectTransform; - var len:Number = Math.sqrt(transform.c*transform.c + transform.g*transform.g + transform.k*transform.k); + len = Math.sqrt(transform.c*transform.c + transform.g*transform.g + transform.k*transform.k); drawUnit.setFragmentConstantsFromNumbers(program.fragmentShader.getVariableIndex("c" + light.lightID + "Direction"), -transform.c/len, -transform.g/len, -transform.k/len, 1); drawUnit.setFragmentConstantsFromNumbers(program.fragmentShader.getVariableIndex("c" + light.lightID + "Color"), light.red, light.green, light.blue); } else if (light is OmniLight) { - var omni:OmniLight = light as OmniLight; + omni = light as OmniLight; transform = light.lightToObjectTransform; rScale = Math.sqrt(transform.a*transform.a + transform.e*transform.e + transform.i*transform.i); rScale += Math.sqrt(transform.b*transform.b + transform.f*transform.f + transform.j*transform.j); @@ -807,14 +813,14 @@ package alternativa.engine3d.materials { drawUnit.setFragmentConstantsFromNumbers(program.fragmentShader.getVariableIndex("c" + light.lightID + "Radius"), 1, omni.attenuationEnd*rScale - omni.attenuationBegin*rScale, omni.attenuationBegin*rScale); drawUnit.setFragmentConstantsFromNumbers(program.fragmentShader.getVariableIndex("c" + light.lightID + "Color"), light.red, light.green, light.blue); } else if (light is SpotLight) { - var spot:SpotLight = light as SpotLight; + spot = light as SpotLight; transform = light.lightToObjectTransform; rScale = Math.sqrt(transform.a*transform.a + transform.e*transform.e + transform.i*transform.i); rScale += Math.sqrt(transform.b*transform.b + transform.f*transform.f + transform.j*transform.j); rScale += len = Math.sqrt(transform.c*transform.c + transform.g*transform.g + transform.k*transform.k); rScale /= 3; - var falloff:Number = Math.cos(spot.falloff*0.5); - var hotspot:Number = Math.cos(spot.hotspot*0.5); + falloff = Math.cos(spot.falloff*0.5); + hotspot = Math.cos(spot.hotspot*0.5); drawUnit.setFragmentConstantsFromNumbers(program.fragmentShader.getVariableIndex("c" + light.lightID + "Position"), transform.d, transform.h, transform.l); drawUnit.setFragmentConstantsFromNumbers(program.fragmentShader.getVariableIndex("c" + light.lightID + "Axis"), -transform.c/len, -transform.g/len, -transform.k/len); @@ -825,14 +831,14 @@ package alternativa.engine3d.materials { } if (shadowedLight){ - var light:Light3D = shadowedLight; + light = shadowedLight; if (light is DirectionalLight) { transform = light.lightToObjectTransform; - var len:Number = Math.sqrt(transform.c*transform.c + transform.g*transform.g + transform.k*transform.k); + len = Math.sqrt(transform.c*transform.c + transform.g*transform.g + transform.k*transform.k); drawUnit.setFragmentConstantsFromNumbers(program.fragmentShader.getVariableIndex("c" + light.lightID + "Direction"), -transform.c/len, -transform.g/len, -transform.k/len, 1); drawUnit.setFragmentConstantsFromNumbers(program.fragmentShader.getVariableIndex("c" + light.lightID + "Color"), light.red, light.green, light.blue); } else if (light is OmniLight) { - var omni:OmniLight = light as OmniLight; + omni = light as OmniLight; transform = light.lightToObjectTransform; rScale = Math.sqrt(transform.a*transform.a + transform.e*transform.e + transform.i*transform.i); rScale += Math.sqrt(transform.b*transform.b + transform.f*transform.f + transform.j*transform.j); @@ -842,14 +848,14 @@ package alternativa.engine3d.materials { drawUnit.setFragmentConstantsFromNumbers(program.fragmentShader.getVariableIndex("c" + light.lightID + "Radius"), 1, omni.attenuationEnd*rScale - omni.attenuationBegin*rScale, omni.attenuationBegin*rScale); drawUnit.setFragmentConstantsFromNumbers(program.fragmentShader.getVariableIndex("c" + light.lightID + "Color"), light.red, light.green, light.blue); } else if (light is SpotLight) { - var spot:SpotLight = light as SpotLight; + spot = light as SpotLight; transform = light.lightToObjectTransform; rScale = Math.sqrt(transform.a*transform.a + transform.e*transform.e + transform.i*transform.i); rScale += Math.sqrt(transform.b*transform.b + transform.f*transform.f + transform.j*transform.j); rScale += len = Math.sqrt(transform.c*transform.c + transform.g*transform.g + transform.k*transform.k); rScale /= 3; - var falloff:Number = Math.cos(spot.falloff*0.5); - var hotspot:Number = Math.cos(spot.hotspot*0.5); + falloff = Math.cos(spot.falloff*0.5); + hotspot = Math.cos(spot.hotspot*0.5); drawUnit.setFragmentConstantsFromNumbers(program.fragmentShader.getVariableIndex("c" + light.lightID + "Position"), transform.d, transform.h, transform.l); drawUnit.setFragmentConstantsFromNumbers(program.fragmentShader.getVariableIndex("c" + light.lightID + "Axis"), -transform.c/len, -transform.g/len, -transform.k/len); @@ -983,6 +989,7 @@ package alternativa.engine3d.materials { if (positionBuffer == null || uvBuffer == null) return; var i:int; + var light:Light3D; if (lightsLength > 0 && (_normalMapSpace == NormalMapSpace.TANGENT_RIGHT_HANDED || _normalMapSpace == NormalMapSpace.TANGENT_LEFT_HANDED)) { if (normalsBuffer == null || tangentsBuffer == null) return; @@ -1011,7 +1018,7 @@ package alternativa.engine3d.materials { var shadowGroup:Vector. = new Vector.(); var firstGroupLength:int = 0; for (i = 0; i < lightsLength; i++) { - var light:Light3D = lights[i]; + light = lights[i]; if (light.shadow!=null && useShadow){ shadowGroup.push(light); } @@ -1082,7 +1089,7 @@ package alternativa.engine3d.materials { ((glossinessMap != null) ? "G" : "g") + ((specularMap != null) ? "S" : "s"); for (var j:int = 0; j < lightLengthInGroup; j++) { - var light:Light3D = lightGroup[j]; + light = lightGroup[j]; materialKey += light.lightID; } @@ -1122,7 +1129,7 @@ package alternativa.engine3d.materials { // For each light we will create new drawUnit for (var j:int = 0; j < shadowGroupLength; j++) { - var light:Light3D = shadowGroup[j]; + light = shadowGroup[j]; // Form key materialKey = (isFirstGroup)?((lightMap != null) ? "L" : "l"):""; materialKey +=