Posted: Sun Aug 16, 2009 8:25 pm
This is getting to an interesting level. Both fairies are nice, though, for now, i rather the small green one, perhaps there should be a competition for it
Official forum of the Irrlicht Engine
https://irrlicht.sourceforge.io/forum/
MasterGod wrote:Nice work.
Well, maybe it is just me but she looks a bit square-ish, if you know what I mean..
Code: Select all
scene::IAnimatedMesh* fairyMesh= smgr->getMesh("../../media/fairy6.b3d");
if (fairyMesh)
{
scene::IMeshManipulator *manipulator = smgr->getMeshManipulator();
scene::IMesh* tangentFairyMesh =
manipulator->createMeshWithTangents(fairyMesh->getMesh(0));
core::matrix4 m;
m.setScale ( core::vector3df(30,30,30) );
manipulator->transformMesh( tangentFairyMesh, m );
scene::ISceneNode *fairy = smgr->addMeshSceneNode(tangentFairyMesh);
fairy->setPosition(core::vector3df(-70,130,45));
video::ITexture* fairyNormalMap = driver->getTexture("../../media/FairyNormal.png");
fairy->setMaterialTexture(1, fairyNormalMap );
fairy->setMaterialType(video::EMT_NORMAL_MAP_SOLID);
tangentFairyMesh->drop();
}
Code: Select all
IMesh* CMeshManipulator::createMeshWithTangents(IMesh* mesh, bool recalculateNormals, bool smooth, bool angleWeighted) const
...
// now calculate tangents
for (b=0; b<meshBufferCount; ++b)
{
const u32 vtxCnt = mesh->getMeshBuffer(b)->getVertexCount();
const u32 idxCnt = clone->getMeshBuffer(b)->getIndexCount();
u16* idx = clone->getMeshBuffer(b)->getIndices();
video::S3DVertexTangents* v =
(video::S3DVertexTangents*)clone->getMeshBuffer(b)->getVertices();
core::vector3df localNormal;
for (u32 i=0; i<idxCnt; i+=3)
{
calculateTangents(
localNormal,
v[idx[i+0]].Tangent,
v[idx[i+0]].Binormal,
v[idx[i+0]].Pos,
v[idx[i+1]].Pos,
v[idx[i+2]].Pos,
v[idx[i+0]].TCoords,
v[idx[i+1]].TCoords,
v[idx[i+2]].TCoords);
//new
v[idx[i+0]].Tangent= v[idx[i+0]].Tangent - v[idx[i+0]].Normal * v[idx[i+0]].Tangent.dotProduct(v[idx[i+0]].Normal) ;
v[idx[i+0]].Tangent.normalize();
v[idx[i+0]].Binormal = v[idx[i+0]].Tangent.crossProduct(v[idx[i+0]].Normal);
v[idx[i+0]].Binormal.normalize();
calculateTangents(
localNormal,
v[idx[i+1]].Tangent,
v[idx[i+1]].Binormal,
v[idx[i+1]].Pos,
v[idx[i+2]].Pos,
v[idx[i+0]].Pos,
v[idx[i+1]].TCoords,
v[idx[i+2]].TCoords,
v[idx[i+0]].TCoords);
//new
v[idx[i+1]].Tangent= v[idx[i+1]].Tangent - v[idx[i+1]].Normal * v[idx[i+1]].Tangent.dotProduct(v[idx[i+1]].Normal) ;
v[idx[i+1]].Tangent.normalize();
v[idx[i+1]].Binormal = v[idx[i+1]].Tangent.crossProduct(v[idx[i+1]].Normal);
v[idx[i+1]].Binormal.normalize();
calculateTangents(
localNormal,
v[idx[i+2]].Tangent,
v[idx[i+2]].Binormal,
v[idx[i+2]].Pos,
v[idx[i+0]].Pos,
v[idx[i+1]].Pos,
v[idx[i+2]].TCoords,
v[idx[i+0]].TCoords,
v[idx[i+1]].TCoords);
//new
v[idx[i+2]].Tangent= v[idx[i+2]].Tangent - v[idx[i+0]].Normal * v[idx[i+2]].Tangent.dotProduct(v[idx[i+2]].Normal) ;
v[idx[i+2]].Tangent.normalize();
v[idx[i+2]].Binormal = v[idx[i+2]].Tangent.crossProduct(v[idx[i+2]].Normal);
v[idx[i+2]].Binormal.normalize();
}
}
Code: Select all
// choose one of them:
#define USE_NVIDIA_GLH_VERSION // use version used by nvidia in glh headers
//#define USE_IRR_VERSION
Code: Select all
void CSkinnedMesh::calculateTangents(
core::vector3df& normal,
core::vector3df& tangent,
core::vector3df& binormal,
core::vector3df& vt1, core::vector3df& vt2, core::vector3df& vt3, // vertices
core::vector2df& tc1, core::vector2df& tc2, core::vector2df& tc3) // texture coords
{
tangent.set(0,0,0);
binormal.set(0,0,0);
core::vector3df v1(vt2.X - vt1.X, tc2.X - tc1.X, tc2.Y - tc1.Y);
core::vector3df v2(vt3.X - vt1.X, tc3.X - tc1.X, tc3.Y - tc1.Y);
core::vector3df txb = v1.crossProduct(v2);
if ( !core::iszero ( txb.X ) )
{
tangent.X = -txb.Y / txb.X;
binormal.X = -txb.Z / txb.X;
}
v1.X = vt2.Y - vt1.Y;
v2.X = vt3.Y - vt1.Y;
txb = v1.crossProduct(v2);
if ( !core::iszero ( txb.X ) )
{
tangent.Y = -txb.Y / txb.X;
binormal.Y = -txb.Z / txb.X;
}
v1.X = vt2.Z - vt1.Z;
v2.X = vt3.Z - vt1.Z;
txb = v1.crossProduct(v2);
if ( !core::iszero ( txb.X ) )
{
tangent.Z = -txb.Y / txb.X;
binormal.Z = -txb.Z / txb.X;
}
tangent = tangent - normal * tangent.dotProduct(normal);
tangent.normalize();
binormal = tangent.crossProduct(normal);
binormal.normalize();
}
Code: Select all
// add animated character
mesh = smgr->getMesh("fairy.b3d");
if (mesh->getMeshType() == scene::EAMT_SKINNED)
{
// Get the skinned mesh and convert it
scene::ISkinnedMesh* skinned = (scene::ISkinnedMesh*)mesh;
skinned->convertMeshToTangents();
// set the material(s) (there's only one in this case)
u32 c = skinned->getMeshBufferCount();
for (u32 i=0; i < c; ++i)
{
skinned->getMeshBuffer(i)->getMaterial().TextureLayer[0].Texture = driver->getTexture("FairyDiffuse.png");
skinned->getMeshBuffer(i)->getMaterial().TextureLayer[1].Texture = driver->getTexture("FairyNormal.png");
skinned->getMeshBuffer(i)->getMaterial().MaterialType = video::EMT_NORMAL_MAP_SOLID;
}
}
scene::IAnimatedMeshSceneNode* anode = 0;
anode = smgr->addAnimatedMeshSceneNode(mesh);
anode->setPosition(core::vector3df(-50,20,-60));
anode->setRotation(core::vector3df(0,180,0));
anode->setAnimationSpeed(15);
// add shadow
anode->addShadowVolumeSceneNode();
smgr->setShadowColor(video::SColor(150,0,0,0));
// make the model a little bit bigger and normalize its normals
// because of the scaling, for correct lighting
anode->setScale(core::vector3df(20,20,20));
anode->setMaterialFlag(video::EMF_NORMALIZE_NORMALS, true);