Game Development Community

fxRenderObject for TSE

by Tony Richards · 08/12/2005 (12:44 pm) · 13 comments

Download Code File

Although I did the TSE port, the hard stuff was done by Melvyn May. This includes the updated documentation of how to create a self rendering SceneObject.

For some reason if you define a material that has a specular, it crashes.

I use this material for testing (it uses the images from the terrain / water demo as the texture)
new Material(renderobject)
{
   baseTex[0] = "dots";

   // Don't uncomment these... it doesn't work yet
   //pixelSpecular[0] = true;
   //specular[0] = "1.0 1.0 1.0 0.1";
   //specularPower[0] = 32.0;
   
   doubleSided = true;  // Works, but only for fxRenderObject classes
   
   // You can use these values, but for some reason, the object
   // becomes *too* translucent with water behind it.
   //translucent = true;
   //translucentZWrite = false;
   //translucentBlendOp = "LerpAlpha";
  
};

Add this block to your mission.
new fxRenderObject() {
      position = "250 125 57.5434";
      rotation = "1 0 0 0";
      scale = "1 1 1";
      quadsize = "5";
      quadrotatespeed = "30";
      material = "renderobject";
   };

Also, one last TODO: Maybe someone can help me translate this?
// Rotate Quad by current roation.
   // TODO: Port this!  How do I rotate?
   //glRotatef(mCurrentAngle, 0,0,1);

Enjoy.

About the author

I am the founder of IndieZen.org, a website dedicated to the Indie 2.0 Revolution where a number of Indie game development studios and individuals collaborate and share a suite of custom built open source game development tools and middleware.


#1
08/12/2005 (2:11 pm)
Download not working - You will need to upload it again for it to work correctly.
#2
08/12/2005 (7:50 pm)
Ok, I fixed the download so it should work now.

I also added code to support the "doubleSided = true;" in the material. TSE doesn't currently support double sided textures from what I could see, so what I did was simply copy the vertices and swapped the normals. There might be another way to do this, but it works well.

I've not done the rotation portion yet. I'm sure it's just a couple of lines of code, but I'm currently sidetracked with other things :P.

I also split up part of the render() function and made a virtual initVertexBuffer() function and placed the vertex creation there. This makes it so you can simply derive a new class from fxRenderObject, provide a new initVertexBuffer() and voila, a different shape with all of the rendering capabilities already built-in without having to add anything else.
#3
08/15/2005 (11:57 pm)
perfect... I swear i was just about to try this one..
#4
08/17/2005 (11:05 am)
Oops, I left out a little chunk of code for making things double sided.

In primBuilder.h in the PrimBuild namespace, add this.

// Call before endToBuffer but after
   // you've created all of the double sided primitives.
   // This currently only works on GFXTriangleList vertex buffers.
   void makeDoubleSided();

And in primBuilder.cpp, add this

void makeDoubleSided()
{
   // TR: I don't know how to mae anything except a triangle
   // list double sided.
   if (mType == GFXTriangleList)
   {
      AssertFatal(mCurVertIndex % 3 == 0, "PrimBuild::makeDoubleSided called for incomplete triangle list");
      U32 numVertices = mCurVertIndex;

      for(U32 x = 0; x < numVertices; x += 3)
      {
         GFXVertexPCT& vert1 = mVertBuff[x];
         GFXVertexPCT& vert2 = mVertBuff[x + 1];
         GFXVertexPCT& vert3 = mVertBuff[x + 2];

         GFXVertexPCT *vert;
         
         // Swap vertices 1 and 3, but keep the texture coordinates 
         // and the color the same and keep vertex 2 the same.
         vert = &mVertBuff[mCurVertIndex++];
         vert->point = vert3.point;
         vert->color = vert1.color;
         vert->texCoord = vert1.texCoord;

         vert = &mVertBuff[mCurVertIndex++];
         vert->point = vert2.point;
         vert->color = vert2.color;
         vert->texCoord = vert2.texCoord;

         vert = &mVertBuff[mCurVertIndex++];
         vert->point = vert1.point;
         vert->color = vert3.color;
         vert->texCoord = vert3.texCoord;
      }
   }
}

If someone wants to make the double sided work with things other than GFXTriangleList then that'd be great! :P
#5
09/07/2006 (9:57 am)
Have you ported this one to MS4? I've tried to run it, but nothing is rendered
#6
09/07/2006 (10:14 am)
OK - got it rendering - sort of.

I changed the prepRenderImage to be

bool fxRenderObject::prepRenderImage(	SceneState* state, const U32 stateKey, const U32 startZone,
										const bool modifyBaseZoneState)
{
   if (isLastState(state, stateKey))
      return false;
   setLastState(state, stateKey);

   // This should be sufficient for most objects that don't manage zones, and
   //  don't need to return a specialized RenderImage...

   if( (state->isObjectRendered(this) || gClientSceneGraph->isReflectPass()) )
   {
      renderObject( state , NULL);
   }

   return false;
}

and fixed the light to use the new sunlight

// grab the sun data from the light manager
   const LightInfo *sunlight = gClientSceneGraph->getLightManager()->sgGetSpecialLight(LightManager::sgSunLightType);
   VectorF sunVector = sunlight->mDirection;

+ a few lines further down one grabs the ambient by using sunlight-> instead of lights[0]

Thats about it

BUT! Adding it to the water demo, it only renders from the horizon and down - anything above the horizon gets cut of.
#7
09/07/2006 (11:51 am)
Finally - got it rendering completely

Some changes - header file. New renderObject interface. Delete the old
// SceneObject
	void renderObject(SceneState* state, RenderInst *ri);

prepRenderImage needs to be like this
bool fxRenderObject::prepRenderImage(	SceneState* state, const U32 stateKey, const U32 startZone,
										const bool modifyBaseZoneState)
{
   if (isLastState(state, stateKey))
      return false;
   setLastState(state, stateKey);

   // This should be sufficient for most objects that don't manage zones, and
   //  don't need to return a specialized RenderImage...

	if (state->isObjectRendered(this))
   {
      RenderInst *ri = gRenderInstManager.allocInst();
	   ri->obj = this;
	   ri->state = state;
	   ri->type = RenderInstManager::RIT_Object;
	   ri->translucent = false;
	   ri->calcSortPoint(this, state->getCameraPosition());
	   gRenderInstManager.addInst(ri);
   }

   return false;
}

Enjoy!
#8
08/21/2008 (1:50 pm)
Has anyone tried this in 1.7.1? I'm having issues.

I have it compiling perfectly ok, no crashes on runtime either. The issue is that it never actually appears to render. (Kind of a problem huh? :D)

prepRenderImage() is called and inside that gRenderInstManager.addInst() is called.

Annoyingly the render function is never called for some reason. I'm not really quite sure why. If I often the editor in game I can see the bounding box etc of my fxrenderobject, just not the actual object :S

Any ideas or suggestions on what I could check?
#9
09/09/2008 (1:58 am)
Craig, did you manage to sort it out for 1.7.x?
#10
09/10/2008 (3:52 pm)
Haven't touched it since to be honest :S
#11
09/11/2008 (3:31 am)
Aright... I managed to use fxFoilageReplicator to do what I wanted, but thanx
#12
11/08/2008 (8:39 am)
I took a stab at getting this into 1.7.1 and I got mixed results.
I can get is into the game and it will render but not correctly.

www.dayofwar.net/images/fxrenderobject/screenshot_001-00000.pngwww.dayofwar.net/images/fxrenderobject/screenshot_001-00001.png
It appears to be rendering the skybox onto the box.

I would really like for someone to take up this code in the spirit of Melv's original code.
When I read Melve's original code I got a clear understanding of how TGE renders an object.
If someone could document how an object is setup and maybe how it is different than TGE I think would be a great help to the community.

I will provide the TGEA 1.7.1 code I worked on so far to help get it started.

fxRenderObject

Edit: I can't believe I posted this 5 months ago and just now realized I linked the wrong file
#13
03/15/2009 (5:55 pm)
This is a working port for TGE 1.7.1.
fxRenderObject TGEA 1.7.1

I will post the TGEA 1.8.+ version as soon as I get it done.