Remaking the irrlicht's fairy

Post your questions, suggestions and experiences regarding to Image manipulation, 3d modeling and level editing for the Irrlicht engine here.
Mel
Competition winner
Posts: 2292
Joined: Wed May 07, 2008 11:40 am
Location: Granada, Spain

Post by Mel »

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 :lol:
"There is nothing truly useless, it always serves as a bad example". Arthur A. Schmitt
jotatsu
Posts: 28
Joined: Sun Mar 18, 2007 1:11 am
Location: Colombia
Contact:

Post by jotatsu »

Well here is the result, at least i resolved the weird ilumination problem (and extra points that christianclavet point out). It was just me being noobish on Blender and dont looking at that little property "double sided" in the edit panel :oops: .

Model is 3506 triangles now, one texture/uv with diffuse, normal and ambient (from xnormal), if anyone want to experiment with a specular map i can remake it too. Now its working with example 08. SpecialFX from 1.5.1

Image

http://file.black-byte.com/Fairy.rar

It can be put in the sdk as its (half or quarter the resolution of the texture and convert it to jpg). If anyone want to add more detail, more clothes, less clothes or wash the "macho" face :lol: , bake etc., the package contain all the files to do so (low, base mid, and high sculpt res models, textures and blender animated one ), feel free to do so.

Btw i didnt now the other Virion's project, but looks cool too. I like the SD chara style, and it will be useful for example for toon shader demos and because the shape it can be down to fewer polygons than the other models in the sdk.


Btw im trying to use parallax maps but the smooth normals are lose in the process.


Image
Last edited by jotatsu on Tue Aug 18, 2009 3:02 pm, edited 2 times in total.
Virion
Competition winner
Posts: 2148
Joined: Mon Dec 18, 2006 5:04 am

Post by Virion »

looks nice so far!
MasterGod
Posts: 2061
Joined: Fri May 25, 2007 8:06 pm
Location: Israel
Contact:

Post by MasterGod »

Nice work.

Well, maybe it is just me but she looks a bit square-ish, if you know what I mean..
Image
Dev State: Abandoned (For now..)
Requirements Analysis Doc: ~87%
UML: ~0.5%
jotatsu
Posts: 28
Joined: Sun Mar 18, 2007 1:11 am
Location: Colombia
Contact:

Post by jotatsu »

MasterGod wrote:Nice work.

Well, maybe it is just me but she looks a bit square-ish, if you know what I mean..

what you mean? like this

Image

Anyway, its there any way to make normal map works with curved smooth surfaces? im losing the smooth normals and idk if its me doing something wrong or its a bug or what. This is the code (a trivial mod of example 11. per pixel lightning):

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

I have tried different parameters of:

createMeshWithTangents(fairyMesh->getMesh(0),false/true,false/true,false/true)

Doesnt work, neith do:

manipulator->recalculateNormals(tangentFairyMesh,true,false);

any ideas?
BlindSide
Admin
Posts: 2821
Joined: Thu Dec 08, 2005 9:09 am
Location: NZ!

Post by BlindSide »

It's probably a bug, I haven't seen anyone manage smooth normals with Irrlicht's built in Parallax mapping shader.

I recommend trying TGM's opengl normal mapping shader as that usually works fine.
ShadowMapping for Irrlicht!: Get it here
Need help? Come on the IRC!: #irrlicht on irc://irc.freenode.net
jotatsu
Posts: 28
Joined: Sun Mar 18, 2007 1:11 am
Location: Colombia
Contact:

Post by jotatsu »

Je i thought it was me doing some mess with the code, anyway, i played a little with the irrlicht's source, using this tutorial http://www.3dkingdoms.com/weekly/weekly.php?a=37 , in the Gram-Schmidt orthogonalization part:

tangent -= normal * tangent.dot( normal );
tangent.normalize();



In CMeshManipulator.cpp

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

	}
And in void

CMeshManipulator::calculateTangents
...

Code: Select all

	// choose one of them:
	#define USE_NVIDIA_GLH_VERSION // use version used by nvidia in glh headers
	//#define USE_IRR_VERSION
The IRR_VERSION seem to have some artifacts in the nose, hands, etc, when the tangent is weird with respect of the normal, so i use the Nvidia version.

And now things are smooth

Image
Image
Virion
Competition winner
Posts: 2148
Joined: Mon Dec 18, 2006 5:04 am

Post by Virion »

i see a little artifacts on the skin... or is that the texture problem? (baked ambient occlusion)

anyway good job!
BlindSide
Admin
Posts: 2821
Joined: Thu Dec 08, 2005 9:09 am
Location: NZ!

Post by BlindSide »

Freckles :P
ShadowMapping for Irrlicht!: Get it here
Need help? Come on the IRC!: #irrlicht on irc://irc.freenode.net
Mel
Competition winner
Posts: 2292
Joined: Wed May 07, 2008 11:40 am
Location: Granada, Spain

Post by Mel »

The flat like surfaces of the normal mapped version appear because you used the CreateMeshWithTangents methods. I never got anything proper with that, i had to calculate the tangent space vectors in shader. so they'd appear well.

But seems that modification has worked well.
"There is nothing truly useless, it always serves as a bad example". Arthur A. Schmitt
bitplane
Admin
Posts: 3204
Joined: Mon Mar 28, 2005 3:45 am
Location: England
Contact:

Post by bitplane »

As per your jotatsu's instructions, I replaced calculateTangents in CSkinnedMesh.cpp:

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();
}
Then I load in the special effects example, like so:

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);
The result isn't quite perfect; there's slight creases in the face and on the arm. I'm not sure if this is because of a problem with the normal map. Can someone else try with a modern normal mapping shader?

Image
Submit bugs/patches to the tracker!
Need help right now? Visit the chat room
FuzzYspo0N
Posts: 914
Joined: Fri Aug 03, 2007 12:43 pm
Location: South Africa
Contact:

Post by FuzzYspo0N »

Im on it now, will post back results asap from some other engines
jotatsu
Posts: 28
Joined: Sun Mar 18, 2007 1:11 am
Location: Colombia
Contact:

Post by jotatsu »

It could be the model/texture, this is a view in xnormal

Image

The texture seams cause problems and also the shoulder's bend in the animation is not that clean (im still a noobish "low poly" modeler). Or it could be artifacts with the tangent calculation, is there any other normal mapped model to test?
FuzzYspo0N
Posts: 914
Joined: Fri Aug 03, 2007 12:43 pm
Location: South Africa
Contact:

Post by FuzzYspo0N »

You could render it in blender itself to test the maps and the mesh probably,

Also the seaming on the arm from the normal maps, i havent looked closely but, dont turn islands around in a normal map. If you have, these seams are likely to occur .

Iv linked an article to explain better

http://boards.polycount.net/showpost.ph ... stcount=25

Check that, iv seen it multiple times recently even in my own work :)
Virion
Competition winner
Posts: 2148
Joined: Mon Dec 18, 2006 5:04 am

Post by Virion »

use the texture without ambient occlusion and see how the result will be
Post Reply