нормализованы нормали и тангенты

This commit is contained in:
Leonid Gaev
2012-04-17 14:42:47 +06:00
parent 58ff32a76a
commit 2057b5dacd
2 changed files with 65 additions and 38 deletions

View File

@@ -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);
}
}
}

View File

@@ -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.<Light3D> = new Vector.<Light3D>();
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 +=