Linker error with COpenGLTexture

If you are a new Irrlicht Engine user, and have a newbie-question, this is the forum for you. You may also post general programming questions here.
Post Reply
timetokill
Posts: 74
Joined: Tue Jul 22, 2008 4:28 am
Location: Los Angeles

Linker error with COpenGLTexture

Post by timetokill »

I tried implementing varmint's MotionTrailSceneNode today (http://irrlicht.sourceforge.net/phpBB2/ ... torder=asc), and I've run into the dreaded linker error.

I fully expect rogerborg to come in here and scold me for overlooking something simple... in fact I'm kind of hoping for it ;) I'd love for it to be a simple problem.

Here's my situation:

I've been looking to implement a sort of ribbon/trail effect for some time, and after searching the forums a lot I found varmint's solution, which looked good but only works with OpenGL. I was having issues with OpenGL earlier that seem to be resolved so I decided to give varmint's code a shot.

Now it seems no matter what I do, I get a linker error:

Code: Select all

1>CMotionTrailSceneNode.obj : error LNK2019: unresolved external symbol "public: unsigned int __thiscall irr::video::COpenGLTexture::getOpenGLTextureName(void)const " (?getOpenGLTextureName@COpenGLTexture@video@irr@@QBEIXZ) referenced in function "public: virtual void __thiscall irr::scene::CMotionTrailSceneNode::render(void)" (?render@CMotionTrailSceneNode@scene@irr@@UAEXXZ)
1>C:\Documents and Settings\RJ Layton\Desktop\thesis\mars\Debug\mars.exe : fatal error LNK1120: 1 unresolved externals
I have found the specific line and even the command that is messing it up: (line surrounded by ***)

Code: Select all

const video::ITexture* texture = trailMaterial.getTexture(0);
	if (texture) {
		*** glBindTexture(GL_TEXTURE_2D, static_cast<const video::COpenGLTexture*>(texture)->getOpenGLTextureName()); ***
	}
The specific issue seems to be with the getOpenGLTextureName() function. When I try to go to the definition of it, it just takes me to the header file. The only way for me to look at the source is to open that file directly, which seems out of line with how I can usually open it with a "Go To Definition" command.

If I comment out the line, the program compiles fine. If I take out the command entirely and just supply an integer there it works fine as well. However, I can't seem to get that line to work on its own.

I've tried compiling the Irrlicht engine with the CMotionTrailSceneNode stuff (and IMotionTrailSceneNode) and following varmint's instructions, but I get this error. I've tried just including all of this source into my own code and including it in main.cpp, and the same error occurs.

I've been trying this and that to remedy it but nothing has worked. I'm sure the solution is simple but I can't figure it out :( Any help would be greatly appreciated.
rogerborg
Admin
Posts: 3590
Joined: Mon Oct 09, 2006 9:36 am
Location: Scotland - gonnae no slag aff mah Engleesh
Contact:

Post by rogerborg »

I'm always the very soul of politeness; you're probably thinking of that vicious fudgeknuckle JP.

I don't know what process varmint was following to get that to work, since class methods are deliberately not exposed in Irrlicht.lib. To access COpenGLTexture::getOpenGLTextureName(), CMotionTrailSceneNode has to be part of the engine proper, but then you get the same problem: you can't simply create a new object from the user app.

Here's a patch for SVN 1668 that exposes the motion trail scene node through the scene manager. I don't intend to commit it though, since it would need more work, and I'm stuck transforming frustums at the moment. :(
Please upload candidate patches to the tracker.
Need help now? IRC to #irrlicht on irc.freenode.net
How To Ask Questions The Smart Way
hybrid
Admin
Posts: 14144
Joined: Wed Apr 19, 2006 9:20 pm
Location: Oldenburg(Oldb), Germany
Contact:

Post by hybrid »

Both Linux and OSX linkers do expose the symbols, even if there's no DLL_EXPORT in front of them. So by simply including the header you'd get access to them. This might change in the next years, but for now it would work.
However, it's usually not a good idea to use those driver related functions, but clean up the render process instead and make it use the official public render and material methods from Irrlicht.
timetokill
Posts: 74
Joined: Tue Jul 22, 2008 4:28 am
Location: Los Angeles

Post by timetokill »

Rogerborg, I'll never even suggest anything negative about you again :) The patch worked! All of this has lead to me connecting to the SVN repository and applying my first patch -- I'm definitely learning a lot.

A parting question -- should I isolate this irrlicht folder and its code to its own area, no longer connected to the repository? I'm wondering if future SVN updates will overwrite the patched code or in general how I should tackle that issue.

In the meantime, thanks again, you're a paragon of politeness.


Edit: It seems my enthusiasm came a bit too soon. While the patch worked with the irrlicht svn download that I did, irrlicht no longer seems to work with my application :( I keep getting errors like: "Run-Time Check Failure #0 - The value of ESP was not properly saved across a function call..." and a bad pointer in "tmp" which is being passed in getNextToken in CSTLMeshFileLoader::getNextVector()..

way above my head, in other words :oops:

Any suggested course of action? Is there a simple fix to this issue, am I forgetting something? What I did was use TortoiseSVN to checkout the Irrlicht source and then I applied the patch, and ran Example04 with the new code -- which was the earlier success. Trying to link into my standing code failed.


Last Edit: The problem appears to be tied to IrrNewt, now I know I'm really gonna get it ;) I guess the IrrNewt.dll is trying to use the irrlicht library in a certain way that got changed since version 1.4.2? Eh.
hybrid
Admin
Posts: 14144
Joined: Wed Apr 19, 2006 9:20 pm
Location: Oldenburg(Oldb), Germany
Contact:

Post by hybrid »

If you change headers of the library you have to recompile not just the library, but also all applications that use these headers. Otherwise the member functions are wrongly used and your app will execute code that was never meant to be executed that way :o
timetokill
Posts: 74
Joined: Tue Jul 22, 2008 4:28 am
Location: Los Angeles

Post by timetokill »

hybrid,

That was a great suggestion, I totally forgot to do that.

However, I did get a problem:

IrrNewt uses the older version of ITerrainSceneNode.h, which has this function:

Code: Select all

virtual void getMeshBufferForLOD(SMeshBufferLightMap& mb, s32 LOD) const = 0;
The svn has changed iterrainscenenode.h to use this version of the function:

Code: Select all

virtual void getMeshBufferForLOD(IDynamicMeshBuffer& mb, s32 LOD) const = 0;

So in IrrNewt's collision.cpp, I get errors here in Newton's NewtonCollision* CreateCollisionTreeTerrain():

Code: Select all

//some code above...

scene::SMeshBufferLightMap mb2;
    ((scene::ITerrainSceneNode*)node)->getMeshBufferForLOD(
		mb2,
		LOD //level of detail
		); 

	mb2.Indices.set_free_when_destroyed(false);
    mb2.Vertices.set_free_when_destroyed(false);

	video::S3DVertex2TCoords  *vertices = (video::S3DVertex2TCoords*)mb2.getVertices(); 
	u16 *indices = mb2.getIndices();

	core::vector3df mapsize = node->getScale();

//more code below...
... the error:
"Error 125 error C2664: 'irr::scene::ITerrainSceneNode::getMeshBufferForLOD' : cannot convert parameter 1 from 'irr::scene::SMeshBufferLightMap' to 'irr::scene::IDynamicMeshBuffer &' c:\Documents and Settings\RJ Layton\Desktop\thesis\mars\irrNewt\source\IrrNewt_src\collision.cpp 37"


I tried making mb2 a IDynamicMeshBuffer, but that just created more problems, from not being able to use mb2.Indices.set_free_when_destroyed, and then also the "cannot create abstract class" for IDynamicMeshBuffer. I saw in the changelist that a lot of changes have been made to how meshes are handled so this isn't especially surprising.
CuteAlien
Admin
Posts: 10058
Joined: Mon Mar 06, 2006 2:25 pm
Location: Tübingen, Germany
Contact:

Post by CuteAlien »

timetokill wrote:A parting question -- should I isolate this irrlicht folder and its code to its own area, no longer connected to the repository? I'm wondering if future SVN updates will overwrite the patched code or in general how I should tackle that issue.
If a future update changes the code touched by that patch you might get conflicts. It's always a little tricky to depart from the official sources. I usually put my own irrlicht version into an own folder. And by now I learned to keep the patches which I apply to it also into an extra folder so I know what was changed. And I learned to create a patch for each of my own changes immediately (working with mercurial helps there a lot as it makes creating patches trivial). I don't any longer update that private irrlicht version from svn, but only do patch bugs which got fixed in the official tree if I need those bugfixes. And once in a while (like once or twice per year) I might update to a newer irrlicht version and apply all the patches which I kept in the separate folder again to that newer version.

Not sure if this is the best way to work, so any improvements on that way of working by others are welcome :-)
IRC: #irrlicht on irc.libera.chat
Code snippet repository: https://github.com/mzeilfelder/irr-playground-micha
Free racer made with Irrlicht: http://www.irrgheist.com/hcraftsource.htm
hybrid
Admin
Posts: 14144
Joined: Wed Apr 19, 2006 9:20 pm
Location: Oldenburg(Oldb), Germany
Contact:

Post by hybrid »

I thought that irrNewt is just a wrapper, didn't know it contains a whole Irrlicht version. I guess you have to integrate the changes into irrNewt then, or stay with version 1.4.x
zillion42
Posts: 324
Joined: Wed Aug 29, 2007 12:32 am
Location: Hamburg, Germany

Post by zillion42 »

hmm.... any solutions... I previously compiled irrnewt with 1.42, but after upgrading to the SVN build I get exactly that error:

1>.\IrrNewt_src\collision.cpp(37) : error C2664: 'irr::scene::ITerrainSceneNode::getMeshBufferForLOD': Konvertierung des Parameters 1 von 'irr::scene::SMeshBufferLightMap' in 'irr::scene::IDynamicMeshBuffer &' nicht möglich

changing

scene::SMeshBufferLightMap mb2;

to

scene::IDynamicMeshBuffer mb2;

generates 5 more erros...
help appreciated...
zillion42
Posts: 324
Joined: Wed Aug 29, 2007 12:32 am
Location: Hamburg, Germany

Post by zillion42 »

I worked around that by declaring a getMeshBufferForLOD_old in CTerrainSceneNode.h & ITerrainSceneNode.h (+ #include "SMeshBufferLightMap.h") and copying the old (previous version) function to CTerrainNode.cpp

Code: Select all

//! Gets the meshbuffer data based on a specified Level of Detail.
	//! \param mb: A reference to an SMeshBuffer object
	//! \param LOD: The Level Of Detail you want the indices from.
	void CTerrainSceneNode::getMeshBufferForLOD_old(SMeshBufferLightMap& mb, s32 LOD ) const
	{
		if (!Mesh.getMeshBufferCount())
			return;

		if ( LOD < 0 )
			LOD = 0;
		else if ( LOD > TerrainData.MaxLOD - 1 )
			LOD = TerrainData.MaxLOD - 1;

		s32 numVertices = Mesh.getMeshBuffer( 0 )->getVertexCount ( );
		mb.Vertices.reallocate ( numVertices );
		video::S3DVertex2TCoords* vertices = (video::S3DVertex2TCoords*)Mesh.getMeshBuffer ( 0 )->getVertices ( );

		s32 i;
		for (i=0; i<numVertices; ++i)
			mb.Vertices.push_back(vertices[i]);

		// calculate the step we take for all patches, since LOD is the same
		s32 step = 1 << LOD;
		s32 index11;
		s32 index21;
		s32 index12;
		s32 index22;

		// Generate the indices for all patches at the specified LOD
		for (i=0; i<TerrainData.PatchCount; ++i)
		{
			for (s32 j=0; j<TerrainData.PatchCount; ++j)
			{
				s32 index = i*TerrainData.PatchCount + j;
				s32 x = 0;
				s32 z = 0;

				// Loop through patch and generate indices
				while (z < TerrainData.CalcPatchSize)
				{
					index11 = getIndex( j, i, index, x, z );
					index21 = getIndex( j, i, index, x + step, z );
					index12 = getIndex( j, i, index, x, z + step );
					index22 = getIndex( j, i, index, x + step, z + step );

					mb.Indices.push_back( index12 );
					mb.Indices.push_back( index11 );
					mb.Indices.push_back( index22 );
					mb.Indices.push_back( index22 );
					mb.Indices.push_back( index11 );
					mb.Indices.push_back( index21 );

					// increment index position horizontally
					x += step;

					if (x >= TerrainData.CalcPatchSize) // we've hit an edge
					{
						x = 0;
						z += step;
					}
				}
			}
		}
	}
not really elegant, anyway a solution
hybrid
Admin
Posts: 14144
Joined: Wed Apr 19, 2006 9:20 pm
Location: Oldenburg(Oldb), Germany
Contact:

Post by hybrid »

I added some example code to tutorial 12. It' rather easy to get the vertices out of the terrain node. You have to check the SVN, though, or wait for the final release of 1.5.
Post Reply