From Terry Welsh, added checks to incoming Geometry for existance of normals,

and if they are present use these to compute the tanget and binormals
vectors perpendicular to existing normals.
This commit is contained in:
Robert Osfield 2004-06-04 08:24:13 +00:00
parent 0fac56f56a
commit 2cf45b50c9
2 changed files with 144 additions and 49 deletions

View File

@ -58,7 +58,7 @@ namespace osgUtil
virtual ~TangentSpaceGenerator() {}
TangentSpaceGenerator &operator=(const TangentSpaceGenerator &) { return *this; }
void compute_basis_vectors(osg::PrimitiveSet *pset, const osg::Array *vx, const osg::Array *tx, int iA, int iB, int iC);
void compute_basis_vectors(osg::PrimitiveSet *pset, const osg::Array *vx, const osg::Array *nx, const osg::Array *tx, int iA, int iB, int iC);
private:
osg::ref_ptr<osg::Vec4Array> T_;

View File

@ -23,6 +23,7 @@ TangentSpaceGenerator::TangentSpaceGenerator(const TangentSpaceGenerator &copy,
void TangentSpaceGenerator::generate(osg::Geometry *geo, int normal_map_tex_unit)
{
const osg::Array *vx = geo->getVertexArray();
const osg::Array *nx = geo->getNormalArray();
const osg::Array *tx = geo->getTexCoordArray(normal_map_tex_unit);
if (!vx || !tx) return;
@ -44,14 +45,14 @@ void TangentSpaceGenerator::generate(osg::Geometry *geo, int normal_map_tex_unit
case osg::PrimitiveSet::TRIANGLES:
for (i=0; i<N; i+=3) {
compute_basis_vectors(pset, vx, tx, i, i+1, i+2);
compute_basis_vectors(pset, vx, nx, tx, i, i+1, i+2);
}
break;
case osg::PrimitiveSet::QUADS:
for (i=0; i<N; i+=4) {
compute_basis_vectors(pset, vx, tx, i, i+1, i+2);
compute_basis_vectors(pset, vx, tx, i+2, i+3, i);
compute_basis_vectors(pset, vx, nx, tx, i, i+1, i+2);
compute_basis_vectors(pset, vx, nx, tx, i+2, i+3, i);
}
break;
@ -63,9 +64,9 @@ void TangentSpaceGenerator::generate(osg::Geometry *geo, int normal_map_tex_unit
unsigned iN = static_cast<unsigned>(*pi-2);
for (i=0; i<iN; ++i, ++j) {
if ((i%2) == 0) {
compute_basis_vectors(pset, vx, tx, j, j+1, j+2);
compute_basis_vectors(pset, vx, nx, tx, j, j+1, j+2);
} else {
compute_basis_vectors(pset, vx, tx, j+1, j, j+2);
compute_basis_vectors(pset, vx, nx, tx, j+1, j, j+2);
}
}
j += 2;
@ -73,9 +74,9 @@ void TangentSpaceGenerator::generate(osg::Geometry *geo, int normal_map_tex_unit
} else {
for (i=0; i<N-2; ++i) {
if ((i%2) == 0) {
compute_basis_vectors(pset, vx, tx, i, i+1, i+2);
compute_basis_vectors(pset, vx, nx, tx, i, i+1, i+2);
} else {
compute_basis_vectors(pset, vx, tx, i+1, i, i+2);
compute_basis_vectors(pset, vx, nx, tx, i+1, i, i+2);
}
}
}
@ -88,13 +89,13 @@ void TangentSpaceGenerator::generate(osg::Geometry *geo, int normal_map_tex_unit
for (osg::DrawArrayLengths::const_iterator pi=dal->begin(); pi!=dal->end(); ++pi) {
unsigned iN = static_cast<unsigned>(*pi-2);
for (i=0; i<iN; ++i) {
compute_basis_vectors(pset, vx, tx, 0, j+1, j+2);
compute_basis_vectors(pset, vx, nx, tx, 0, j+1, j+2);
}
j += 2;
}
} else {
for (i=0; i<N-2; ++i) {
compute_basis_vectors(pset, vx, tx, 2, i+1, i+2);
compute_basis_vectors(pset, vx, nx, tx, 2, i+1, i+2);
}
}
break;
@ -131,7 +132,7 @@ void TangentSpaceGenerator::generate(osg::Geometry *geo, int normal_map_tex_unit
}
}
void TangentSpaceGenerator::compute_basis_vectors(osg::PrimitiveSet *pset, const osg::Array *vx, const osg::Array *tx, int iA, int iB, int iC)
void TangentSpaceGenerator::compute_basis_vectors(osg::PrimitiveSet *pset, const osg::Array *vx, const osg::Array *nx, const osg::Array *tx, int iA, int iB, int iC)
{
iA = pset->index(iA);
iB = pset->index(iB);
@ -171,6 +172,41 @@ void TangentSpaceGenerator::compute_basis_vectors(osg::PrimitiveSet *pset, const
osg::notify(osg::WARN) << "Warning: TangentSpaceGenerator: vertex array must be Vec2Array, Vec3Array or Vec4Array" << std::endl;
}
osg::Vec3 N1;
osg::Vec3 N2;
osg::Vec3 N3;
if(nx)
{
switch (nx->getType())
{
case osg::Array::Vec2ArrayType:
for (i=0; i<2; ++i) {
N1.ptr()[i] = static_cast<const osg::Vec2Array&>(*nx)[iA].ptr()[i];
N2.ptr()[i] = static_cast<const osg::Vec2Array&>(*nx)[iB].ptr()[i];
N3.ptr()[i] = static_cast<const osg::Vec2Array&>(*nx)[iC].ptr()[i];
}
break;
case osg::Array::Vec3ArrayType:
N1 = static_cast<const osg::Vec3Array&>(*nx)[iA];
N2 = static_cast<const osg::Vec3Array&>(*nx)[iB];
N3 = static_cast<const osg::Vec3Array&>(*nx)[iC];
break;
case osg::Array::Vec4ArrayType:
for (i=0; i<3; ++i) {
N1.ptr()[i] = static_cast<const osg::Vec4Array&>(*nx)[iA].ptr()[i];
N2.ptr()[i] = static_cast<const osg::Vec4Array&>(*nx)[iB].ptr()[i];
N3.ptr()[i] = static_cast<const osg::Vec4Array&>(*nx)[iC].ptr()[i];
}
break;
default:
osg::notify(osg::WARN) << "Warning: TangentSpaceGenerator: normal array must be Vec2Array, Vec3Array or Vec4Array" << std::endl;
}
}
osg::Vec2 uv1;
osg::Vec2 uv2;
osg::Vec2 uv3;
@ -203,47 +239,106 @@ void TangentSpaceGenerator::compute_basis_vectors(osg::PrimitiveSet *pset, const
osg::notify(osg::WARN) << "Warning: TangentSpaceGenerator: texture coord array must be Vec2Array, Vec3Array or Vec4Array" << std::endl;
}
osg::Vec3 face_normal = (P2 - P1) ^ (P3 - P1);
if(nx){
osg::Vec3 V, T1, T2, T3, B1, B2, B3;
osg::Vec3 V;
V = osg::Vec3(P2.x() - P1.x(), uv2.x() - uv1.x(), uv2.y() - uv1.y()) ^
osg::Vec3(P3.x() - P1.x(), uv3.x() - uv1.x(), uv3.y() - uv1.y());
if (V.x() != 0) {
V.normalize();
T1.x() += -V.y() / V.x();
B1.x() += -V.z() / V.x();
T2.x() += -V.y() / V.x();
B2.x() += -V.z() / V.x();
T3.x() += -V.y() / V.x();
B3.x() += -V.z() / V.x();
}
V = osg::Vec3(P2.x() - P1.x(), uv2.x() - uv1.x(), uv2.y() - uv1.y()) ^
osg::Vec3(P3.x() - P1.x(), uv3.x() - uv1.x(), uv3.y() - uv1.y());
if (V.x() != 0) {
V.normalize();
(*T_)[iA].x() += -V.y() / V.x();
(*B_)[iA].x() += -V.z() / V.x();
(*T_)[iB].x() += -V.y() / V.x();
(*B_)[iB].x() += -V.z() / V.x();
(*T_)[iC].x() += -V.y() / V.x();
(*B_)[iC].x() += -V.z() / V.x();
V = osg::Vec3(P2.y() - P1.y(), uv2.x() - uv1.x(), uv2.y() - uv1.y()) ^
osg::Vec3(P3.y() - P1.y(), uv3.x() - uv1.x(), uv3.y() - uv1.y());
if (V.x() != 0) {
V.normalize();
T1.y() += -V.y() / V.x();
B1.y() += -V.z() / V.x();
T2.y() += -V.y() / V.x();
B2.y() += -V.z() / V.x();
T3.y() += -V.y() / V.x();
B3.y() += -V.z() / V.x();
}
V = osg::Vec3(P2.z() - P1.z(), uv2.x() - uv1.x(), uv2.y() - uv1.y()) ^
osg::Vec3(P3.z() - P1.z(), uv3.x() - uv1.x(), uv3.y() - uv1.y());
if (V.x() != 0) {
V.normalize();
T1.z() += -V.y() / V.x();
B1.z() += -V.z() / V.x();
T2.z() += -V.y() / V.x();
B2.z() += -V.z() / V.x();
T3.z() += -V.y() / V.x();
B3.z() += -V.z() / V.x();
}
osg::Vec3 tempvec;
tempvec = N1 ^ T1;
(*T_)[iA] = osg::Vec4(tempvec ^ N1, 0);
tempvec = B1 ^ N1;
(*B_)[iA] = osg::Vec4(N1 ^ tempvec, 0);
tempvec = N2 ^ T2;
(*T_)[iB] = osg::Vec4(tempvec ^ N2, 0);
tempvec = B2 ^ N2;
(*B_)[iB] = osg::Vec4(N2 ^ tempvec, 0);
tempvec = N3 ^ T3;
(*T_)[iC] = osg::Vec4(tempvec ^ N3, 0);
tempvec = B3 ^ N3;
(*B_)[iC] = osg::Vec4(N3 ^ tempvec, 0);
(*N_)[iA] += osg::Vec4(N1, 0);
(*N_)[iB] += osg::Vec4(N2, 0);
(*N_)[iC] += osg::Vec4(N3, 0);
}
else{
osg::Vec3 face_normal = (P2 - P1) ^ (P3 - P1);
V = osg::Vec3(P2.y() - P1.y(), uv2.x() - uv1.x(), uv2.y() - uv1.y()) ^
osg::Vec3(P3.y() - P1.y(), uv3.x() - uv1.x(), uv3.y() - uv1.y());
if (V.x() != 0) {
V.normalize();
(*T_)[iA].y() += -V.y() / V.x();
(*B_)[iA].y() += -V.z() / V.x();
(*T_)[iB].y() += -V.y() / V.x();
(*B_)[iB].y() += -V.z() / V.x();
(*T_)[iC].y() += -V.y() / V.x();
(*B_)[iC].y() += -V.z() / V.x();
osg::Vec3 V;
V = osg::Vec3(P2.x() - P1.x(), uv2.x() - uv1.x(), uv2.y() - uv1.y()) ^
osg::Vec3(P3.x() - P1.x(), uv3.x() - uv1.x(), uv3.y() - uv1.y());
if (V.x() != 0) {
V.normalize();
(*T_)[iA].x() += -V.y() / V.x();
(*B_)[iA].x() += -V.z() / V.x();
(*T_)[iB].x() += -V.y() / V.x();
(*B_)[iB].x() += -V.z() / V.x();
(*T_)[iC].x() += -V.y() / V.x();
(*B_)[iC].x() += -V.z() / V.x();
}
V = osg::Vec3(P2.y() - P1.y(), uv2.x() - uv1.x(), uv2.y() - uv1.y()) ^
osg::Vec3(P3.y() - P1.y(), uv3.x() - uv1.x(), uv3.y() - uv1.y());
if (V.x() != 0) {
V.normalize();
(*T_)[iA].y() += -V.y() / V.x();
(*B_)[iA].y() += -V.z() / V.x();
(*T_)[iB].y() += -V.y() / V.x();
(*B_)[iB].y() += -V.z() / V.x();
(*T_)[iC].y() += -V.y() / V.x();
(*B_)[iC].y() += -V.z() / V.x();
}
V = osg::Vec3(P2.z() - P1.z(), uv2.x() - uv1.x(), uv2.y() - uv1.y()) ^
osg::Vec3(P3.z() - P1.z(), uv3.x() - uv1.x(), uv3.y() - uv1.y());
if (V.x() != 0) {
V.normalize();
(*T_)[iA].z() += -V.y() / V.x();
(*B_)[iA].z() += -V.z() / V.x();
(*T_)[iB].z() += -V.y() / V.x();
(*B_)[iB].z() += -V.z() / V.x();
(*T_)[iC].z() += -V.y() / V.x();
(*B_)[iC].z() += -V.z() / V.x();
}
(*N_)[iA] += osg::Vec4(face_normal, 0);
(*N_)[iB] += osg::Vec4(face_normal, 0);
(*N_)[iC] += osg::Vec4(face_normal, 0);
}
V = osg::Vec3(P2.z() - P1.z(), uv2.x() - uv1.x(), uv2.y() - uv1.y()) ^
osg::Vec3(P3.z() - P1.z(), uv3.x() - uv1.x(), uv3.y() - uv1.y());
if (V.x() != 0) {
V.normalize();
(*T_)[iA].z() += -V.y() / V.x();
(*B_)[iA].z() += -V.z() / V.x();
(*T_)[iB].z() += -V.y() / V.x();
(*B_)[iB].z() += -V.z() / V.x();
(*T_)[iC].z() += -V.y() / V.x();
(*B_)[iC].z() += -V.z() / V.x();
}
(*N_)[iA] += osg::Vec4(face_normal, 0);
(*N_)[iB] += osg::Vec4(face_normal, 0);
(*N_)[iC] += osg::Vec4(face_normal, 0);
}