Question about vector2d and S3DVertex

Discuss about anything related to the Irrlicht Engine, or read announcements about any significant features or usage changes.
Spintz
Posts: 1688
Joined: Thu Nov 04, 2004 3:25 pm

Question about vector2d and S3DVertex

Post by Spintz »

Ok, so in order to add support 8 textures, I also need to add 8 texture coordinates. So here's my plan so far -

In S3DVertex.h change -

Code: Select all

core::vector2d< f32 > TCoords1;
core::vector2d< f32 > TCoords2;
core::vector2d< f32 > TCoords3;
core::vector2d< f32 > TCoords4;
core::vector2d< f32 > TCoords5;
core::vector2d< f32 > TCoords6;
core::vector2d< f32 > TCoords7;
core::vector2d< f32 > TCoords8;
to

Code: Select all

union
{
	struct
	{
		core::vector2d< f32 > TCoords1;
		core::vector2d< f32 > TCoords2;
		core::vector2d< f32 > TCoords3;
		core::vector2d< f32 > TCoords4;
		core::vector2d< f32 > TCoords5;
		core::vector2d< f32 > TCoords6;
		core::vector2d< f32 > TCoords7;
		core::vector2d< f32 > TCoords8;
	};

	core::vector2d< f32 > TCoords[8];
};
This is a similar setup to the Texture pointers in SMaterial.h where you have this -

Code: Select all

union
{
	struct
	{
		//! First texture layer.
		ITexture* Texture1;	

		//! Second texture layer
		ITexture* Texture2;	

		//! Third texture layer
		ITexture* Texture3;	

		//! Fourth texture layer
		ITexture* Texture4;	

		//! Fifth texture layer
		ITexture* Texture5;	

		//! Sixth texture layer
		ITexture* Texture6;	

		//! Seventh texture layer
		ITexture* Texture7;	

		//! Eigth texture layer
		ITexture* Texture8;	
	};

	//! Array of textures, the same as accessing through Texture1 and Texture2
	ITexture* Textures[MATERIAL_MAX_TEXTURES];
};
The major difference/issue is that in the SMaterial, ITexture objects are allocated elsewhere, and SMaterial simply holds pointers to them.

Yes, I am getting to the point soon!!!!!

So, the problem is, that in order for core::vector2d to be used as an object in a union, and not as a pointer, it can have ONLY a default constructor and no assignment operator or copy constructor. This isn't so bad, and only a few changes are required throughout code, as you can no longer do -

Code: Select all

core::vector2df vec2d( pointX, pointY );
You now would have to do -

Code: Select all

core::vector2df vec2d;
vec2d.set(pointX,pointY);
Would anyone have a problem with that? Making the TCoords a union and struct with pointers, would mean allocation and de-allocation with new in the contructor and destructor for S3DVertex, which I don't like at all. So, what do ya think?
Image
Spintz
Posts: 1688
Joined: Thu Nov 04, 2004 3:25 pm

Post by Spintz »

Here's an example of this code working in IrrSpintz :D

Using these textures on the heightmap -

Base Texture -
Image
Detail Texture -
Image
Alpha 1 Texture -
Image
Alpha 2 Texture -
Image
Alpha 3 Texture -
Image

So, in application, I do this -

Code: Select all

terrain->getMaterial(0).Texture1 = driver->getTexture( "../../media/drygrass1.jpg" );
terrain->getMaterial(0).Texture2 = driver->getTexture( "../../media/detailmap.jpg" );
terrain->getMaterial(0).Texture3 = driver->getTexture( "../../media/bottomgreen.tga" );
terrain->getMaterial(0).Texture4 = driver->getTexture( "../../media/topleftblue.tga" );
terrain->getMaterial(0).Texture5 = driver->getTexture( "../../media/toprightred.tga" );
terrain->setMaterialType(video::EMT_SOLID );
And then I've added 3 new materials -

Code: Select all

//! Detail mapped material, with a 3rd texture to be used as an alpha map.
//! The first texture is diffuse color map, the second is added to this and usually 
//! displayed with a bigger scale value so that it adds more detail.  The third texutre
//! is blended into the detail mapped texture based on the 3rd textures alpha values.
EMT_DETAIL_ALPHA,

//! Detail mapped material, with a 3rd texture to be used as an alpha map.
//! The first texture is diffuse color map, the second is added to this and usually 
//! displayed with a bigger scale value so that it adds more detail.  The third texutre
//! is blended into the previous two, based on it's alpha values.  The fourth texture 
//! is blended into the previous three, using it's own alpha values.
EMT_DETAIL_2ALPHA,

//! Detail mapped material, with a 3rd texture to be used as an alpha map.
//! The first texture is diffuse color map, the second is added to this and usually 
//! displayed with a bigger scale value so that it adds more detail.  The third texutre
//! is blended into the previous two, based on it's alpha values.  The fourth texture 
//! is blended into the previous three, using it's own alpha values.  The fifth texture
//! is blended into the previous four, using it's own alpha values.
EMT_DETAIL_3ALPHA,
And here's the results -

Solid -
Image
Detail Map -
Image
Detail 1 Alpha -
Image
Detail 2 Alpha -
Image
Detail 3 Alpha -
Image

Notice the transparency on the alpha maps is working. And also notice, that the texture are now properly applied to the terrain ( I'm looking at the terrain from the left, or the camera is at ~[-500,500,500] and looking at the terrain center. There was a bug where the top of the texture would be on the "left" of the terrain, and that is now fixed as well.

I should have this new IrrSpintz release by the end of the week, or this weekend sometime. I'm working on update the documentation ALOT to show the new features of IrrSpintz right in the .chm file! :D
Image
Spintz
Posts: 1688
Joined: Thu Nov 04, 2004 3:25 pm

Post by Spintz »

Oh and BTW, I only have this working for DirectX9. Here's the DETAIL_3ALPHA material class in DirectX9, if anyone can translate this to OpenGL for me, it would make this new release much quicker, otherwise, i'm gonna have to hunt around in OpenGL.

Code: Select all

//! material renderer to test alpha maps 
class CD3D9MaterialRenderer_DETAIL_3ALPHA : public CD3D9MaterialRenderer
{
public:

	CD3D9MaterialRenderer_DETAIL_3ALPHA(IDirect3DDevice9* p, video::IVideoDriver* d)
		: CD3D9MaterialRenderer(p, d) {}

	virtual void OnSetMaterial(SMaterial& material, const SMaterial& lastMaterial,
		bool resetAllRenderstates, IMaterialRendererServices* services) 
	{
		if (material.MaterialType != lastMaterial.MaterialType || resetAllRenderstates)
		{
			pID3DDevice->SetTextureStageState( 0, D3DTSS_COLOROP, D3DTOP_MODULATE );
			pID3DDevice->SetTextureStageState( 0, D3DTSS_COLORARG1, D3DTA_TEXTURE );
			pID3DDevice->SetTextureStageState( 0, D3DTSS_COLORARG2, D3DTA_DIFFUSE );
			pID3DDevice->SetTextureStageState( 0, D3DTSS_ALPHAOP,  D3DTOP_DISABLE );

			pID3DDevice->SetTextureStageState( 1, D3DTSS_COLOROP, D3DTOP_ADDSIGNED );
			pID3DDevice->SetTextureStageState( 1, D3DTSS_COLORARG1, D3DTA_TEXTURE );
			pID3DDevice->SetTextureStageState( 1, D3DTSS_COLORARG2, D3DTA_CURRENT );

			pID3DDevice->SetTextureStageState( 2, D3DTSS_COLOROP, D3DTOP_BLENDTEXTUREALPHA );
			pID3DDevice->SetTextureStageState( 2, D3DTSS_COLORARG1, D3DTA_TEXTURE );
			pID3DDevice->SetTextureStageState( 2, D3DTSS_COLORARG2, D3DTA_CURRENT );
			pID3DDevice->SetTextureStageState( 2, D3DTSS_ALPHAOP,  D3DTOP_ADD );
			pID3DDevice->SetTextureStageState( 2, D3DTSS_ALPHAARG1, D3DTA_TEXTURE );
			pID3DDevice->SetTextureStageState( 2, D3DTSS_ALPHAARG2, D3DTA_CURRENT );

			pID3DDevice->SetTextureStageState( 3, D3DTSS_COLOROP, D3DTOP_BLENDTEXTUREALPHA );
			pID3DDevice->SetTextureStageState( 3, D3DTSS_COLORARG1, D3DTA_TEXTURE );
			pID3DDevice->SetTextureStageState( 3, D3DTSS_COLORARG2, D3DTA_CURRENT );
			pID3DDevice->SetTextureStageState( 3, D3DTSS_ALPHAOP,  D3DTOP_ADD );
			pID3DDevice->SetTextureStageState( 3, D3DTSS_ALPHAARG1, D3DTA_TEXTURE );
			pID3DDevice->SetTextureStageState( 3, D3DTSS_ALPHAARG2, D3DTA_CURRENT );

			pID3DDevice->SetTextureStageState( 4, D3DTSS_COLOROP, D3DTOP_BLENDTEXTUREALPHA );
			pID3DDevice->SetTextureStageState( 4, D3DTSS_COLORARG1, D3DTA_TEXTURE );
			pID3DDevice->SetTextureStageState( 4, D3DTSS_COLORARG2, D3DTA_CURRENT );
			pID3DDevice->SetTextureStageState( 4, D3DTSS_ALPHAOP,  D3DTOP_ADD );
			pID3DDevice->SetTextureStageState( 4, D3DTSS_ALPHAARG1, D3DTA_TEXTURE );
			pID3DDevice->SetTextureStageState( 4, D3DTSS_ALPHAARG2, D3DTA_CURRENT );

			pID3DDevice->SetTextureStageState( 5, D3DTSS_COLOROP, D3DTOP_DISABLE );
			pID3DDevice->SetTextureStageState( 5, D3DTSS_ALPHAOP, D3DTOP_DISABLE );

			pID3DDevice->SetRenderState( D3DRS_ALPHABLENDENABLE, TRUE );
			pID3DDevice->SetRenderState( D3DRS_SRCBLEND, D3DBLEND_SRCALPHA );
			pID3DDevice->SetRenderState( D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA );
		}

		services->setBasicRenderStates(material, lastMaterial, resetAllRenderstates);
	}

	virtual void OnUnsetMaterial() 
	{ 
		pID3DDevice->SetRenderState( D3DRS_ALPHATESTENABLE, FALSE );
	} 
};
Image
Eternl Knight
Posts: 313
Joined: Tue Nov 01, 2005 5:01 am

Post by Eternl Knight »

Is this implemented in the downloadable version of irrlicht-spnitz yet?

--EK
Guest

Post by Guest »

This way the vertices will be a lot bigger in size.
This could affect a lot rendering speed, especially if rendering without hw vertex buffers.
Spintz
Posts: 1688
Joined: Thu Nov 04, 2004 3:25 pm

Post by Spintz »

No, it's not downloadable yet. I was hoping for this weekend but OpenGL is really messed up. I have fixed a HUGE bug with openGL rendering, the way irrlicht setup the rendering in the drawIndexed* functions was completely wrong and out of order.

Take this function for example, in Irrlicht-0.12 :

Code: Select all

//! draws an indexed triangle list
void COpenGLDriver::drawIndexedTriangleList(const S3DVertex2TCoords* vertices, s32 vertexCount, 
										   const u16* indexList, s32 triangleCount)
{
	if (!checkPrimitiveCount(triangleCount))
		return;

	CNullDriver::drawIndexedTriangleList(vertices, vertexCount, indexList, triangleCount);

	setRenderStates3DMode();

	glEnableClientState(GL_COLOR_ARRAY);
	glEnableClientState(GL_VERTEX_ARRAY);
	glEnableClientState(GL_TEXTURE_COORD_ARRAY );
	glEnableClientState(GL_NORMAL_ARRAY );

	// convert colors to gl color format.

	const S3DVertex2TCoords* p = vertices;
	ColorBuffer.set_used(vertexCount);
	for (s32 i=0; i<vertexCount; ++i)
	{
		ColorBuffer[i] = p->Color.toOpenGLColor();
		++p;
	}

	// draw everything

	glColorPointer(4, GL_UNSIGNED_BYTE, sizeof(video::SColor), &ColorBuffer[0]);
	glNormalPointer(GL_FLOAT, sizeof(S3DVertex2TCoords), &vertices[0].Normal);
	glVertexPointer(3, GL_FLOAT, sizeof(S3DVertex2TCoords),  &vertices[0].Pos);

	// texture coordiantes
	if (MultiTextureExtension)
	{
		extGlClientActiveTextureARB(GL_TEXTURE0_ARB);
		glEnableClientState ( GL_TEXTURE_COORD_ARRAY );
		glTexCoordPointer(2, GL_FLOAT, sizeof(S3DVertex2TCoords), &vertices[0].TCoords);
		
		extGlClientActiveTextureARB(GL_TEXTURE1_ARB);
		glEnableClientState ( GL_TEXTURE_COORD_ARRAY );
		glTexCoordPointer(2, GL_FLOAT, sizeof(S3DVertex2TCoords), &vertices[0].TCoords2);
	}
	else
		glTexCoordPointer(2, GL_FLOAT, sizeof(S3DVertex2TCoords), &vertices[0].TCoords);

	glDrawElements(GL_TRIANGLES, triangleCount * 3, GL_UNSIGNED_SHORT, indexList);

	glFlush();

	glDisableClientState(GL_COLOR_ARRAY);
	glDisableClientState(GL_VERTEX_ARRAY);

	if (MultiTextureExtension)
	{
		extGlClientActiveTextureARB(GL_TEXTURE0_ARB);
		glDisableClientState ( GL_TEXTURE_COORD_ARRAY );

		extGlClientActiveTextureARB(GL_TEXTURE1_ARB);
		glDisableClientState ( GL_TEXTURE_COORD_ARRAY );
	}
	else
		glDisableClientState(GL_TEXTURE_COORD_ARRAY );

	glDisableClientState(GL_NORMAL_ARRAY );
}

It should be :

Code: Select all

//! draws an indexed triangle list
void COpenGLDriver::drawIndexedTriangleList(const S3DVertex2TCoords* vertices, s32 vertexCount, 
										   const u16* indexList, s32 triangleCount)
{
	if (!checkPrimitiveCount(triangleCount))
		return;

	CNullDriver::drawIndexedTriangleList(vertices, vertexCount, indexList, triangleCount);

	setRenderStates3DMode();

	// convert colors to gl color format.
	const S3DVertex2TCoords* p = vertices;
	ColorBuffer.set_used(vertexCount);
	for (s32 i=0; i<vertexCount; ++i)
	{
		ColorBuffer[i] = p->Color.toOpenGLColor();
		++p;
	}

	// draw everything
	extGlClientActiveTextureARB(GL_TEXTURE0_ARB);
	glEnableClientState(GL_COLOR_ARRAY);
	glColorPointer(4, GL_UNSIGNED_BYTE, sizeof(video::SColor), &ColorBuffer[0]);
	glEnableClientState(GL_VERTEX_ARRAY);
	glVertexPointer(3, GL_FLOAT, sizeof(S3DVertex2TCoords),  &vertices[0].Pos);
	glEnableClientState(GL_NORMAL_ARRAY );
	glNormalPointer(GL_FLOAT, sizeof(S3DVertex2TCoords), &vertices[0].Normal);
	glEnableClientState ( GL_TEXTURE_COORD_ARRAY );
	glTexCoordPointer(2, GL_FLOAT, sizeof(S3DVertex2TCoords), &vertices[0].TCoords);

	// texture coordiantes
	if (MultiTextureExtension)
	{
		extGlClientActiveTextureARB(GL_TEXTURE1_ARB);
		glEnableClientState ( GL_TEXTURE_COORD_ARRAY );
		glTexCoordPointer(2, GL_FLOAT, sizeof(S3DVertex2TCoords), &vertices[0].TCoords2);
	}

	glDrawElements(GL_TRIANGLES, triangleCount * 3, GL_UNSIGNED_SHORT, indexList);

	glFlush();

	extGlClientActiveTextureARB(GL_TEXTURE0_ARB);
	glDisableClientState( GL_VERTEX_ARRAY );
	glDisableClientState( GL_NORMAL_ARRAY );
	glDisableClientState( GL_COLOR_ARRAY );
	glDisableClientState( GL_TEXTURE_COORD_ARRAY );

	if (MultiTextureExtension)
	{
		extGlClientActiveTextureARB( GL_TEXTURE1_ARB );
		glDisableClientState( GL_TEXTURE_COORD_ARRAY );
	}
}
To explain this further, ( I'm just learning OpenGL so it's all new to me ), but when you are setting up client states, you need to set them up for each texture unit. So calling -

Code: Select all

glDisableClientState( GL_VERTEX_ARRAY );
glDisableClientState( GL_NORMAL_ARRAY );
glDisableClientState( GL_COLOR_ARRAY );
glDisableClientState( GL_TEXTURE_COORD_ARRAY );
without specifying

Code: Select all

extGlClientActiveTextureARB(GL_TEXTURE0_ARB);
Will disable those client states for whichever texture unit happens to be left active, which, in the original code for this function, was GL_TEXTURE_ARB1, so it was disabling the 2nd texture stage, not the first. Also, as a point, for the more than 8 texture support, you have to enable the client state for each texture unit.

Also, the major difference between DirectX and OpenGL texture stage setup, is that in DirectX, if I do this -

Code: Select all

pID3DDevice->SetTextureStageState( 1, D3DTSS_COLOROP, D3DTOP_DISABLE );
pID3DDevice->SetTextureStageState( 1, D3DTSS_ALPHAOP,  D3DTOP_DISABLE );
That will disable the 2nd texture stage and any texture stage after it. In OpenGL, you need to disable each texture unit. Disabling the 2nd texture unit, does not disable the 3rd texture unit and beyond. So, with 8 textures, for the EMT_SOLID material, you need to do -

Code: Select all

if (Driver->hasMultiTextureExtension())
{
	Driver->setTexture( 1, 0 );
	Driver->setTexture( 2, 0 );
	Driver->setTexture( 3, 0 );
	Driver->setTexture( 4, 0 );
	Driver->setTexture( 5, 0 );
	Driver->setTexture( 6, 0 );
	Driver->setTexture( 7, 0 );
}
Phew, anyways, there are still more OpenGL bugs to workout, like transparency issues, which I am determined to figure out!

As far as the vertices being a lot bigger in size, I'm going to try and add a setup, where you can specify the number of texture coords per vertex, so if you're only using 2 texture coords, only 2 will be enabled in the vertex format.

The new release of IrrSpintz is gonna be delayed prolly till sometime next week or next weekend, while I work these issues out. Sorry.
Image
MikeR
Posts: 767
Joined: Sun Dec 26, 2004 4:03 pm
Location: Northern California USA
Contact:

Post by MikeR »

Spitz,
Great work there. Didn't someone already fix the transperancy problem in OGL?
I thought I read somewhere on the forum where they did.
If it exists in the real world, it can be created in 3d

Sys specs:
AMD 3700+ 64 processor
1.0 gb ram
e-Geforce 6600 graphics 256 mb onboard ram
Spintz
Posts: 1688
Joined: Thu Nov 04, 2004 3:25 pm

Post by Spintz »

I've read a few posts that talk about the OpenGL transparency problem fixed, but from what I can tell, from the ones I've seen, they are hacks, because the OpenGL rendering states are all fubar'd. I really don't know OpenGL, I know DirectX, they are very similar so I think I know what to expect from OpenGL and I can at least compare the results with DirectX results, knowing that DirectX does the right thing ( and is easier for me to fix if need be ). I want to learn OpenGL, so I'm reviewing the entire render process for OpenGL in the material and throughout COpenGLDriver class.

Oh, and it's Spintz :D I correct you cause for some reason, lots of people read my nick wrong and someone on IRC actually thought it was spitz for months!!! ;)
Image
Eternl Knight
Posts: 313
Joined: Tue Nov 01, 2005 5:01 am

Post by Eternl Knight »

Well, OpenGL is my primary domain (as I work on apps that need to run on Win32, Mac OSX, & Linux in my "day job"). So if you ever need to ask someone somoething - I'm around :)

Though, you seem to be getting the hang of some common "gotcha" areas (such as the need to select the texture unit before setting render states) so I'm guessing you won't be needing me :D

Look forward to your release!

--EK
MikeR
Posts: 767
Joined: Sun Dec 26, 2004 4:03 pm
Location: Northern California USA
Contact:

Post by MikeR »

Sorry Spentz. :oops: I have a habbit of missing that one little letter.
If you get transperancy working with OGL, would you PLEASE post the code?
If it exists in the real world, it can be created in 3d

Sys specs:
AMD 3700+ 64 processor
1.0 gb ram
e-Geforce 6600 graphics 256 mb onboard ram
Spintz
Posts: 1688
Joined: Thu Nov 04, 2004 3:25 pm

Post by Spintz »

I do need help with OpenGL. I don't yet have transparency working, but before I get to that problem, I'm trying to figure out why the terrain node is untextures unless I also have a 2d item. In my current test, if I don't do guiEnv->drawAll(), then the terrain does not display. If I call guiEnv->drawAll(), then the terrain displays. If you think you can help, anyone that is, I can provide the current code for download so you can test, with the 8 texture support. If you can come to IRC, #irrlicht on irc.freenode.net, it would help. Thanks!!!
Image
Eternl Knight
Posts: 313
Joined: Tue Nov 01, 2005 5:01 am

Post by Eternl Knight »

I cannot come into IRC (as my ISP is a poop about that) - so a download would be good. Given the fact that you have isolated it down to a condition of work/don't-work - it should not be that hard to track down (*laugh* famous last final words!).

Let me know when I can look at it and I'll get onto it.

--EK
Spintz
Posts: 1688
Joined: Thu Nov 04, 2004 3:25 pm

Post by Spintz »

Here's the link for my "In-development" version -

http://irrlicht.spintz.com/downloads/IrrSpintz.rar

The CollisionTest example is what I'm using to test the code with 5 textures for the terrain node. If you have any trouble, post here, PM me or email me. Thanks for the help!!!
Image
Spintz
Posts: 1688
Joined: Thu Nov 04, 2004 3:25 pm

Post by Spintz »

Well, I still haven't been able to figure out why 3D won't display unless 2D is enabled in OpenGL, however, EUREKA on the transparency and alpha maps and more than 2 textures!!!!! :D

Image

The white in the back of the terrain is fog, nothing messed up there! So, now I can get the 3D to work without 2D in openGL, if i reset the 3d renderstates every frame, as well as re-set the material, but that shouldn't be necessary. Maybe I'll release new IrrSpintz with these changes and the "hack" to get 3D working without 2D and then try and find out that problem. Hopefully sometime tomorrow, I can do a new release! :D
Image
Eternl Knight
Posts: 313
Joined: Tue Nov 01, 2005 5:01 am

Post by Eternl Knight »

Would you mind updating the version uploaded on your site with the alpha changes please? I only just downloaded the engine today (it's the weekend here)

--EK
Post Reply