Game Development Community

dev|Pro Game Development Curriculum

Blended texture layer on models

by Dennis Saarela · 06/15/2005 (12:22 am) · 3 comments

This resource will show you how to use the detailmap texturelayer for rendering a blended texture on your models (damage texture)
(WARNING: if you use this, detail textures won't work on the models you apply damage textures to.)

HOW THIS WAS DONE
I added the damageTolerance from the vehicle to the player, so we easy can have different damage levels.
The damage textures are loaded in player.cc then sent through the shape/meshes down to the render pipe.
This can porobably be used on other models too if you add the damageTexture code to shapeBase.cc instead of player.cc (this isn't tested though).

The following files have been altered:

engine:
game/player.cc
game/player.h
ts/tsmesh.cc
ts/tsmesh.h
ts/tsshapeinstance.cc
ts/tsshapeinstance.h

script:
~/server/script/player.cs

A backup of these files are recommended!
I add new functions (altered copies) instead of tweaking the existing once. (I will use code references instead of lines because of this.)
This is my first resource so I hope you understand how to alter your files. Here we go:

(Find the code preceding the "// <-- DS Damage Texture" tags, then enter the code new code)

game/player.cc

PlayerData::PlayerData
groundImpactShakeAmp.set( 20.0, 20.0, 20.0 );
   groundImpactShakeDuration = 1.0;
   groundImpactShakeFalloff = 10.0;

	// <-- DS Damage Texture
    dMemset( damageLevelTolerance, 0, sizeof( damageLevelTolerance ) );

	for(int i=0; i<NUM_DAMAGE_LEVELS; i++)
		damageTexName[i] = "";
	// <-- DS Damage Texture

PlayerData::initPersistFields
addField("groundImpactShakeDuration",  TypeF32,       Offset(groundImpactShakeDuration,   PlayerData));
   addField("groundImpactShakeFalloff",   TypeF32,       Offset(groundImpactShakeFalloff,    PlayerData));

	// <-- DS Damage Texture
   addField("damageLevelTolerance", TypeF32,                      Offset(damageLevelTolerance,  PlayerData), NUM_DAMAGE_LEVELS);
   addField("damageTexture",   TypeFilename, Offset(damageTexName,      PlayerData), NUM_DAMAGE_LEVELS);
	// <-- DS Damage Texture

PlayerData::packData
stream->write(groundImpactShakeDuration);
   stream->write(groundImpactShakeFalloff);

	// <-- DS Damage Texture
	for (int i = 0; i < NUM_DAMAGE_LEVELS; i++)
	{
		stream->writeString(damageTexName[i]);
		stream->write(damageLevelTolerance[i]);
	}
	// <-- DS Damage Texture

PlayerData::unpackData
stream->read(&groundImpactShakeDuration);
   stream->read(&groundImpactShakeFalloff);

	// <-- DS Damage Texture
	for (int i = 0; i < NUM_DAMAGE_LEVELS; i++)
	{
		damageTexName[i] = stream->readSTString();
		stream->read(&damageLevelTolerance[i]);
	}
	// <-- DS Damage Texture

Player::Player
mMountPending = 0;

   // DS Damage Texture -->
   mDamageTextureLevel = -1;
	// <-- DS Damage Texture

Player::onAdd
// <-- DS Damage Texture
      for(int i=0; i<PlayerData::NUM_DAMAGE_LEVELS; i++)
	     if(mDataBlock->damageTexName[i] != StringTable->insert(""))
			mDamageTexture[i] = TextureHandle(mDataBlock->damageTexName[i], MeshTexture, false);
	  // <-- DS Damage Texture

Player::packUpdate
U32 retMask = Parent::packUpdate(con, mask, stream);

	// <-- DS Damage Texture
   stream->write(mDamageTextureLevel);
	// <-- DS Damage Texture

Player::unpackUpdate
Parent::unpackUpdate(con,stream);
   
	// <-- DS Damage Texture
	S32 dmgTL;
	stream->read(&dmgTL);
	if(mDamageTextureLevel != dmgTL)
	{
		mDamageTextureLevel = dmgTL;
		if(mDamageTextureLevel >= 0)
			this->mShapeInstance->setMaterialDamage(&this->mDamageTexture[mDamageTextureLevel]);
		else
			this->mShapeInstance->setMaterialDamage(NULL);
	}
	// <-- DS Damage Texture

at end of file
// <-- DS Damage Texture
ConsoleMethod( Player, setDamageTextureLevel, void, 3, 3, "(S32 level)")
{
	S32 level;
	dSscanf(argv[2], "%d", &level);

	object->setDamageTextureLevel(level); 
}

ConsoleMethod( Player, getDamageTextureLevel, S32, 2, 2, "")
{
	return object->getDamageTextureLevel();
}

void Player::setDamageTextureLevel(S32 level)
{
	mShapeInstance->setMaterialDamage(&this->mDamageTexture[level]);
	mDamageTextureLevel = level;
}

S32 Player::getDamageTextureLevel()
{
	return mDamageTextureLevel;
}
// <-- DS Damage Texture


game/player.h
NumSpineNodes = 6,
      ImpactBits = 3,
      NUM_SPLASH_EMITTERS = 3,
      BUBBLE_EMITTER = 2,
	  // <-- DS Damage Texture
	  NUM_DAMAGE_LEVELS = 4,
	  // <-- DS Damage Texture
   };

ParticleEmitterData* splashEmitterList[NUM_SPLASH_EMITTERS];
   S32 splashEmitterIDList[NUM_SPLASH_EMITTERS];

	// <-- DS Damage Texture
   StringTableEntry damageTexName[NUM_DAMAGE_LEVELS];
   F32 damageLevelTolerance[NUM_DAMAGE_LEVELS];
	// <-- DS Damage Texture

Death()                    {clear();}
      MatrixF* fallToGround(F32 adjust, const Point3F& pos, F32 zrot, F32 boxRad);
   } mDeath;

   // <-- DS Damage Texture   
   TextureHandle mDamageTexture[PlayerData::NUM_DAMAGE_LEVELS];
   S32 mDamageTextureLevel;
   // <-- DS Damage Texture

/// Get the rotation of the head of the player
   const Point3F& getHeadRotation() { return mHead; }
   void getDamageLocation(const Point3F& in_rPos, const char *&out_rpVert, const char *&out_rpQuad);

	// <-- DS Damage Texture
	void setDamageTextureLevel(S32 level);
	S32 getDamageTextureLevel();
	// <-- DS Damage Texture


ts/tsMesh.cc

add function:
// <-- DS Damage Texture
void TSMesh::render(S32 frame, S32 matFrame, TSMaterialList * materials, TextureHandle *damageTexture)
{
   if( vertsPerFrame <= 0 ) {
      return;
   }

   S32 firstVert  = vertsPerFrame * frame;
   S32 firstTVert = vertsPerFrame * matFrame;

   if (getFlags(Billboard))
   {
      if (getFlags(BillboardZAxis))
         forceFaceCameraZAxis();
      else
         forceFaceCamera();
   }

   const Point3F * normals = getNormals(firstVert);
   saveMergeNormals(); // verts & tverts saved and restored on tsshapeinstance::setStatics

   // set up vertex arrays -- already enabled in TSShapeInstance::render
   glVertexPointer(3,GL_FLOAT,0,&verts[firstVert]);
   glNormalPointer(GL_FLOAT,0,normals);
   glTexCoordPointer(2,GL_FLOAT,0,&tverts[firstTVert]);
   if (TSShapeInstance::smRenderData.detailMapMethod == TSShapeInstance::DETAIL_MAP_MULTI_1 ||
       TSShapeInstance::smRenderData.detailMapMethod == TSShapeInstance::DETAIL_MAP_MULTI_2)
   {
      glClientActiveTextureARB(GL_TEXTURE0_ARB + TSShapeInstance::smRenderData.detailMapTE);
      glTexCoordPointer(2,GL_FLOAT,0,&tverts[firstTVert]);
      glClientActiveTextureARB(GL_TEXTURE0_ARB + TSShapeInstance::smRenderData.baseTE);
   }

   // lock...
   bool lockArrays = dglDoesSupportCompiledVertexArray();
   if (lockArrays)
      glLockArraysEXT(0,vertsPerFrame);

   for (S32 i=0; i<primitives.size(); i++)
   {
      TSDrawPrimitive & draw = primitives[i];
      AssertFatal(draw.matIndex & TSDrawPrimitive::Indexed,
                  "TSMesh::render: rendering of non-indexed meshes no longer supported");

      // material change?
      if ( ((TSShapeInstance::smRenderData.materialIndex ^ draw.matIndex) &
            (TSDrawPrimitive::MaterialMask|TSDrawPrimitive::NoMaterial)) != 0)
				setMaterial(draw.matIndex,materials,damageTexture); // <-- Send damageTexture

      S32 drawType = getDrawType(draw.matIndex>>30);

      glDrawElements(drawType,draw.numElements,GL_UNSIGNED_SHORT,&indices[draw.start]);
   }

   // unlock...
   if (lockArrays)
      glUnlockArraysEXT();

   restoreMergeNormals();
}
// <-- DS Damage Texture

add function:
// <-- DS Damage Texture
void TSMesh::setMaterial(S32 matIndex, TSMaterialList* materials, TextureHandle *damageTexture)
{
   if ((matIndex|TSShapeInstance::smRenderData.materialIndex) & TSDrawPrimitive::NoMaterial)
   {
      if (matIndex & TSDrawPrimitive::NoMaterial)
      {
         glDisable(GL_TEXTURE_2D);
         glDisable(GL_BLEND);
         glDepthMask(GL_TRUE);
         TSShapeInstance::smRenderData.materialIndex = matIndex;
         TSShapeInstance::smRenderData.materialFlags &= ~TSMaterialList::Translucent;
         return;
      }
      glEnable(GL_TEXTURE_2D);
   }

   matIndex &= TSDrawPrimitive::MaterialMask;

   U32 flags     = materials->getFlags(matIndex);
   U32 bareFlags = flags;
   if (TSShapeInstance::smRenderData.alwaysAlpha || TSShapeInstance::smRenderData.fadeSet)
      flags |= TSMaterialList::Translucent;
   U32 deltaFlags = flags ^ TSShapeInstance::smRenderData.materialFlags;
   if (TSShapeInstance::smRenderData.environmentMapMethod!=TSShapeInstance::ENVIRONMENT_MAP_MULTI_1)
      deltaFlags &= ~TSMaterialList::NeverEnvMap;

   // update flags and material index...
   TSShapeInstance::smRenderData.materialFlags = flags;
   TSShapeInstance::smRenderData.materialIndex = matIndex;

   if (TSShapeInstance::smRenderData.useOverride == false || bareFlags & TSMaterialList::Translucent)
   {
      TextureHandle & tex = materials->getMaterial(matIndex);
      glBindTexture(GL_TEXTURE_2D, tex.getGLName());
   }
   else
      glBindTexture(GL_TEXTURE_2D, TSShapeInstance::smRenderData.override.getGLName());

   // anything change...?
   if (deltaFlags)
   {
      if (deltaFlags & TSMaterialList::NeverEnvMap && !TSShapeInstance::smRenderData.useOverride )
      {
         glActiveTextureARB(GL_TEXTURE0_ARB + TSShapeInstance::smRenderData.environmentMapTE);
         if (bareFlags & TSMaterialList::NeverEnvMap)
            glDisable(GL_TEXTURE_2D);
         else
            glEnable(GL_TEXTURE_2D);
         glActiveTextureARB(GL_TEXTURE0_ARB + TSShapeInstance::smRenderData.baseTE);
      }
      if (flags & TSMaterialList::Translucent)
      {
         if (TSShapeInstance::smRenderData.fogMethod == TSShapeInstance::FOG_TWO_PASS || TSShapeInstance::smRenderData.fogMethod == TSShapeInstance::FOG_TWO_PASS_TEXGEN)
         {
            TSShapeInstance::smRenderData.vertexAlpha.fog = 1.0f - TSShapeInstance::smRenderData.fogColor.w;
         }
         else if ((TSShapeInstance::smRenderData.fogMethod == TSShapeInstance::FOG_MULTI_1 ||
                  TSShapeInstance::smRenderData.fogMethod == TSShapeInstance::FOG_MULTI_1_TEXGEN) &&
                  flags & (TSMaterialList::Additive|TSMaterialList::Subtractive))
         {
            glActiveTextureARB(GL_TEXTURE0_ARB + TSShapeInstance::smRenderData.fogTE);
            glDisable(GL_TEXTURE_2D);
            glActiveTextureARB(GL_TEXTURE0_ARB + TSShapeInstance::smRenderData.baseTE);
            TSShapeInstance::smRenderData.vertexAlpha.fog = 1.0f - TSShapeInstance::smRenderData.fogColor.w;
         }
         glEnable(GL_BLEND);
         glDepthMask(GL_FALSE);
      }
      else
      {
         if (TSShapeInstance::smRenderData.fogMethod == TSShapeInstance::FOG_TWO_PASS || TSShapeInstance::smRenderData.fogMethod == TSShapeInstance::FOG_TWO_PASS_TEXGEN)
         {
            TSShapeInstance::smRenderData.vertexAlpha.fog = 1.0f;
         }
         else if ((TSShapeInstance::smRenderData.fogMethod == TSShapeInstance::FOG_MULTI_1 ||
                  TSShapeInstance::smRenderData.fogMethod == TSShapeInstance::FOG_MULTI_1_TEXGEN) &&
                  flags & (TSMaterialList::Additive|TSMaterialList::Subtractive))
         {
            glActiveTextureARB(GL_TEXTURE0_ARB + TSShapeInstance::smRenderData.fogTE);
            glEnable(GL_TEXTURE_2D);
            glActiveTextureARB(GL_TEXTURE0_ARB + TSShapeInstance::smRenderData.baseTE);
            TSShapeInstance::smRenderData.vertexAlpha.fog = 1.0f;
         }
         glDisable(GL_BLEND);
         glDepthMask(GL_TRUE);
      }
      if (deltaFlags & (TSMaterialList::Additive|TSMaterialList::Subtractive))
      {
         if (flags & TSMaterialList::Additive)
            glBlendFunc(GL_SRC_ALPHA, GL_ONE);
         else if (flags & TSMaterialList::Subtractive)
            glBlendFunc(GL_ZERO,GL_ONE_MINUS_SRC_COLOR);
         else
            glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);
      }
      if (deltaFlags & TSMaterialList::SelfIlluminating)
      {
         if (TSShapeInstance::smRenderData.detailMapMethod==TSShapeInstance::DETAIL_MAP_MULTI_2)
         {
            // special case:  lighting done on different TE than texture...
            glActiveTextureARB(GL_TEXTURE0_ARB + TSShapeInstance::smRenderData.baseTE + 1);
            if (flags & TSMaterialList::SelfIlluminating)
            {
               // modulate...
               glTexEnvi(GL_TEXTURE_ENV,GL_TEXTURE_ENV_MODE,GL_MODULATE);
            }
            else
            {
               // we need to use the combine extension...we modulate by primary color rather than fragment color
               glTexEnvi(GL_TEXTURE_ENV,GL_TEXTURE_ENV_MODE,GL_COMBINE_EXT);
               glTexEnvi(GL_TEXTURE_ENV,GL_COMBINE_RGB_EXT,GL_MODULATE);
               glTexEnvi(GL_TEXTURE_ENV,GL_SOURCE0_RGB_EXT,GL_PREVIOUS_EXT);
               glTexEnvi(GL_TEXTURE_ENV,GL_OPERAND0_RGB_EXT,GL_SRC_COLOR);
               glTexEnvi(GL_TEXTURE_ENV,GL_SOURCE1_RGB_EXT,GL_PRIMARY_COLOR_EXT);
               glTexEnvi(GL_TEXTURE_ENV,GL_OPERAND1_RGB_EXT,GL_SRC_COLOR);
               glTexEnvi(GL_TEXTURE_ENV,GL_COMBINE_ALPHA_EXT,GL_MODULATE);
               glTexEnvi(GL_TEXTURE_ENV,GL_SOURCE0_ALPHA_EXT,GL_PREVIOUS_EXT);
               glTexEnvi(GL_TEXTURE_ENV,GL_OPERAND0_ALPHA_EXT,GL_SRC_ALPHA);
               glTexEnvi(GL_TEXTURE_ENV,GL_SOURCE1_ALPHA_EXT,GL_PRIMARY_COLOR_EXT);
               glTexEnvi(GL_TEXTURE_ENV,GL_OPERAND1_ALPHA_EXT,GL_SRC_ALPHA);
            }
            glActiveTextureARB(GL_TEXTURE0_ARB + TSShapeInstance::smRenderData.baseTE);
         }
         // turn off lights if self-illuminating (or back on if not)
         if (flags & TSMaterialList::SelfIlluminating || !TSShapeInstance::smRenderData.lightingOn)
            glDisable(GL_LIGHTING);
         else
            glEnable(GL_LIGHTING);
      }
   }

   // gotta set these every time since present value depends on texture not gl state
   glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_S,flags & TSMaterialList::S_Wrap ? GL_REPEAT : GL_CLAMP);
   glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_T,flags & TSMaterialList::T_Wrap ? GL_REPEAT : GL_CLAMP);

   // emap texture...
   if (TSShapeInstance::smRenderData.environmentMapMethod==TSShapeInstance::ENVIRONMENT_MAP_MULTI_3)
   {
      // set emap's texture unit...
      glActiveTextureARB(GL_TEXTURE0_ARB + TSShapeInstance::smRenderData.environmentMapTE + 2);

      if (TSShapeInstance::smRenderData.useOverride == false || flags & TSMaterialList::Translucent)
      {
         TextureHandle & tex = materials->getMaterial(matIndex);
         glBindTexture(GL_TEXTURE_2D, tex.getGLName());
      }
      else
         glBindTexture(GL_TEXTURE_2D, TSShapeInstance::smRenderData.override.getGLName());
      glActiveTextureARB(GL_TEXTURE0_ARB + TSShapeInstance::smRenderData.environmentMapTE);
      glBindTexture(GL_TEXTURE_2D, materials->getReflectionMap(matIndex)->getGLName());

      // set default texture unit...
      glActiveTextureARB(GL_TEXTURE0_ARB + TSShapeInstance::smRenderData.baseTE);
   }

   // dmap texture...
   if (TSShapeInstance::smRenderData.detailMapMethod==TSShapeInstance::DETAIL_MAP_MULTI_1 ||
       TSShapeInstance::smRenderData.detailMapMethod==TSShapeInstance::DETAIL_MAP_MULTI_2)
   {
      // set detail map's texture unit...
      glActiveTextureARB(GL_TEXTURE0_ARB+TSShapeInstance::smRenderData.detailMapTE);

// damageTexture start
      //TextureHandle * detailMap = materials->getDetailMap(matIndex);
      if (damageTexture)
      {
         glEnable(GL_TEXTURE_2D);
         glBindTexture(GL_TEXTURE_2D, damageTexture->getGLName());
      }
// damageTexture end
      else
         glDisable(GL_TEXTURE_2D);

      // set default texture unit...
      glActiveTextureARB(GL_TEXTURE0_ARB + TSShapeInstance::smRenderData.baseTE);
   }

   // translucent materials shouldn't get cloak shifting
   // 1: pushed -> pushed
   // 2: pushed -> not pushed
   // 3: not pushed -> pushed
   // 4: not pushed -> not pushed
   if (TSShapeInstance::smRenderData.textureMatrixPushed)
   {
      if (TSShapeInstance::smRenderData.useOverride && bareFlags & TSMaterialList::Translucent)
      {
         // Leave it alone
      }
      else
      {
         // Pop it off
         glMatrixMode(GL_TEXTURE);
         glPopMatrix();
         glMatrixMode(GL_MODELVIEW);
         TSShapeInstance::smRenderData.textureMatrixPushed = false;
      }
   }
   else
   {
      if (TSShapeInstance::smRenderData.useOverride && bareFlags & TSMaterialList::Translucent)
      {
         // Push it up
         glMatrixMode(GL_TEXTURE);
         glPushMatrix();
         glLoadIdentity();
         glMatrixMode(GL_MODELVIEW);
         TSShapeInstance::smRenderData.textureMatrixPushed = true;
      }
      else
      {
         // leave it alone
      }
   }

   // handle environment map
   if (flags & TSMaterialList::NeverEnvMap)
      TSShapeInstance::smRenderData.vertexAlpha.emap = 1.0f;
   else
      TSShapeInstance::smRenderData.vertexAlpha.emap = TSShapeInstance::smRenderData.environmentMapAlpha * materials->getReflectionAmount(matIndex);
   // handle vertex alpha
   if (TSShapeInstance::smRenderData.vertexAlpha.set())
   {
      Point4F v(1,1,1,TSShapeInstance::smRenderData.vertexAlpha.current);
      glColor4fv(v);
      glMaterialfv(GL_FRONT_AND_BACK,GL_AMBIENT_AND_DIFFUSE,v);
   }

   // set up fade
   if( overrideFadeVal < 1.0f && dglDoesSupportTextureEnvCombine() )
   {
      S32 & emapTE     = TSShapeInstance::smRenderData.environmentMapTE;
      S32 & baseTE     = TSShapeInstance::smRenderData.baseTE;

      if( TSShapeInstance::smRenderData.environmentMapMethod == TSShapeInstance::ENVIRONMENT_MAP_MULTI_1 )
      {
         glActiveTextureARB(GL_TEXTURE0_ARB + emapTE);
         glDisable(GL_TEXTURE_2D);
      }

      glActiveTextureARB(GL_TEXTURE0_ARB + baseTE);

      glEnable( GL_BLEND );

      if( TSShapeInstance::smRenderData.materialFlags & TSMaterialList::Translucent )
      {
         glBlendFunc( GL_SRC_ALPHA, GL_ONE );
      }
      else
      {
         glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA );
      }


      ColorF curColor;
      glGetFloatv( GL_FOG_COLOR, (GLfloat*)&curColor );
      curColor.alpha = overrideFadeVal;
      glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, curColor);

      glTexEnvi(GL_TEXTURE_ENV,GL_TEXTURE_ENV_MODE,GL_COMBINE_EXT);
      glTexEnvi(GL_TEXTURE_ENV,GL_COMBINE_ALPHA_EXT,GL_REPLACE);
      glTexEnvi(GL_TEXTURE_ENV,GL_SOURCE0_ALPHA_EXT,GL_CONSTANT_EXT);
      glTexEnvi(GL_TEXTURE_ENV,GL_OPERAND0_ALPHA_EXT,GL_SRC_ALPHA);


   }
}
// <-- DS Damage Texture

add function:
// <-- DS Damage Texture
void TSMesh::renderDetailMap(S32 frame, S32 matFrame, TSMaterialList * materials, TextureHandle *damageTexture)
{
   // most gl states assumed to be all set up...
   // if we're here, then we're drawing detail map in two passes...

   S32 firstVert  = vertsPerFrame * frame;
   S32 firstTVert = vertsPerFrame * matFrame;

   // set up vertex arrays -- already enabled in TSShapeInstance::render
   glVertexPointer(3,GL_FLOAT,0,&verts[firstVert]);
   glNormalPointer(GL_FLOAT,0,&norms[firstVert]);
   glTexCoordPointer(2,GL_FLOAT,0,&tverts[firstTVert]);

   // lock...
   bool lockArrays = dglDoesSupportCompiledVertexArray();
   if (lockArrays)
      glLockArraysEXT(0,vertsPerFrame);

   S32 matIndex = -1;

   for (S32 i=0; i<primitives.size(); i++)
   {
      TSDrawPrimitive & draw = primitives[i];
      AssertFatal(draw.matIndex & TSDrawPrimitive::Indexed,"TSMesh::render: rendering of non-indexed meshes no longer supported");

      if ( (matIndex ^ draw.matIndex) & (TSDrawPrimitive::MaterialMask|TSDrawPrimitive::NoMaterial))
      {
         // material change
         matIndex = draw.matIndex & (TSDrawPrimitive::MaterialMask|TSDrawPrimitive::NoMaterial);

         if (matIndex & TSDrawPrimitive::NoMaterial)
            // no material...
            continue;
         else
         {
            TSShapeInstance::smRenderData.detailMapTE = 0; // borrow this variable...use as a bool to flag that we have a dmap

			TextureHandle * detailMap = damageTexture;
            if (detailMap)
               glBindTexture(GL_TEXTURE_2D,detailMap->getGLName());
            else
               continue;
            TSShapeInstance::smRenderData.detailMapTE = 1;
		 }
      }
      if (TSShapeInstance::smRenderData.detailMapTE)
         glDrawElements(getDrawType(draw.matIndex>>30),draw.numElements,GL_UNSIGNED_SHORT,&indices[draw.start]);
   }

   // unlock...
   if (lockArrays)
      glUnlockArraysEXT();
}
// <-- DS Damage Texture

add function:
// <-- DS Damage Texture
void TSSkinMesh::render(S32 frame, S32 matFrame, TSMaterialList * materials, TextureHandle *damageTexture)
{
   // update verts and normals...
   updateSkin();

   // render...
   Parent::render(frame,matFrame,materials, damageTexture);
}
// <-- DS Damage Texture


ts/tsMesh.h

class TSMesh
virtual void renderShadow(S32 frame, const MatrixF & mat, S32 dim, U32 * bits, TSMaterialList *);
   void renderEnvironmentMap(S32 frame, S32 matFrame, TSMaterialList *);

	// <-- DS Damage Texture
	virtual void render(S32 frame, S32 matFrame, TSMaterialList *, TextureHandle *damageTexture);
    void renderDetailMap(S32 frame, S32 matFrame, TSMaterialList *, TextureHandle *);
    static void setMaterial(S32 matIndex, TSMaterialList *, TextureHandle *damageTexture);
	// <-- DS Damage Texture

class TSSkinMesh
// render methods..
   void render(S32 frame, S32 matFrame, TSMaterialList *);

   // <-- DS Damage Texture   
   void render(S32 frame, S32 matFrame, TSMaterialList *, TextureHandle *damageTexture);
   // <-- DS Damage Texture


ts/tsShapeInstance.cc

TSShapeInstance::TSShapeInstance * Both Constructors! *
VECTOR_SET_ASSOCIATION(mThreadList);
   VECTOR_SET_ASSOCIATION(mTransitionThreads);

   // <-- DS Damage Texture
   mDamageTexture = NULL;
   // <-- DS Damage Texture

TSShapeInstance::render
replace (around line 664):
    mMeshObjects[i].render(od, mMaterialList);
    
with:
    mMeshObjects[i].render(od, mMaterialList, mDamageTexture);	// <-- DS Damage Texture

replace (around line 675):
   // render detail maps using a second pass?
   if (twoPassDetailMap())
      renderDetailMap();

with:
   // <-- DS Damage Texture
   // render detail maps using a second pass?
   if (twoPassDetailMap() && mDamageTexture)
      renderDetailMap();
	// <-- DS Damage Texture

TSShapeInstance::renderDetailMap()
replace (around 1272):
    mMeshObjects[i].renderDetailMap(od,mMaterialList);
    
with:
    mMeshObjects[i].renderDetailMap(od,mMaterialList,mDamageTexture);	// <-- DS Damage Texture

add function:
// <-- DS Damage Texture
void TSShapeInstance::MeshObjectInstance::render(S32 objectDetail, TSMaterialList * materials, TextureHandle *damageTexture)
{
   if (visible>0.01f)
   {
      TSMesh * mesh = getMesh(objectDetail);
      if (mesh)
      {
         MatrixF * transform = getTransform();
         if (transform != TSShapeInstance::smRenderData.currentTransform)
         {
            if (TSShapeInstance::smRenderData.currentTransform)
               glPopMatrix();
            if (transform)
            {
               glPushMatrix();
               dglMultMatrix(transform);
            }
            TSShapeInstance::smRenderData.currentTransform = transform;
         }
         if (visible>0.99f)
         {
            if (TSShapeInstance::smRenderData.balloonShape)
            {
               glPushMatrix();
               F32 & bv = TSShapeInstance::smRenderData.balloonValue;
               glScalef(bv,bv,bv);
            }

			//
			if(damageTexture)
				mesh->render(frame,matFrame,materials,damageTexture);
			else
				mesh->render(frame,matFrame,materials);
            if (TSShapeInstance::smRenderData.balloonShape)
               glPopMatrix();
         }
         else
         {
            mesh->setFade(visible);
			if(damageTexture) //
				mesh->render(frame,matFrame,materials,damageTexture);
			else //
				mesh->render(frame,matFrame,materials);
            mesh->clearFade();
         }

      }
   }
}
// <-- DS Damage Texture

add function:
// <-- DS Damage Texture
void TSShapeInstance::MeshObjectInstance::renderDetailMap(S32 objectDetail, TSMaterialList * materials, TextureHandle *damageTexture)
{
   if (visible>0.01f)
   {
      TSMesh * mesh = getMesh(objectDetail);
      if (mesh && mesh->getFlags(TSMesh::HasDetailTexture))
      {
         MatrixF * transform = getTransform();
         if (transform != TSShapeInstance::smRenderData.currentTransform)
         {
            if (TSShapeInstance::smRenderData.currentTransform)
               glPopMatrix();
            if (transform)
            {
               glPushMatrix();
               dglMultMatrix(transform);
            }
            TSShapeInstance::smRenderData.currentTransform = transform;
         }

         if (TSShapeInstance::smRenderData.balloonShape)
         {
            glPushMatrix();
            F32 & bv = TSShapeInstance::smRenderData.balloonValue;
            glScalef(bv,bv,bv);
         }		 
         mesh->renderDetailMap(frame,matFrame,materials,damageTexture);
         if (TSShapeInstance::smRenderData.balloonShape)
            glPopMatrix();
      }
   }
}
// <-- DS Damage Texture

add function:
// <-- DS Damage Texture
void TSShapeInstance::setMaterialDamage(TextureHandle* pTexHandle)
{	
	mDamageTexture = pTexHandle;
	mMaxDetailMapDL = mShape->details.size(); // Set this to make sure the dmg texture is painted...
}
// <-- DS Damage Texture


ts/tsShapeInstance.h

/// This just selects the right detail level (mesh) and calls mesh's render
      /// @{
      void render(S32 objectDetail, TSMaterialList *);

	  // <-- DS Damage Texture
	  void render(S32 objectDetail, TSMaterialList *, TextureHandle *damageTexture);
      void renderDetailMap(S32 objectDetail, TSMaterialList *, TextureHandle *damageTexture = NULL);
	  // <-- DS Damage Texture

//-------------------------------------------------------------------------------------
// animate, render, & detail control
//-------------------------------------------------------------------------------------

   public:

	// <-- DS Damage Texture
	void setMaterialDamage(TextureHandle* pTexHandle);
	TextureHandle* mDamageTexture;
	// <-- DS Damage Texture


That was the engine. Now for the script file:


server/script/player.cs


At the end of the datablock add (and remember to add some damage textures (with a nice alpha)):
// <-- DS Damage Texture
    damageLevelTolerance[0] = 0.25;
    damageLevelTolerance[1] = 0.50;
    damageLevelTolerance[2] = 0.75;
   
   damageTexture[0]                = "~/data/shapes/player/dmg/dmg1";
   damageTexture[1]                = "~/data/shapes/player/dmg/dmg2";
   damageTexture[2]                = "~/data/shapes/player/dmg/dmg3";
   // <-- DS Damage Texture

replace the onDamage function with this:
function Armor::onDamage(%this, %obj, %delta)
{
   // This method is invoked by the ShapeBase code whenever the 
   // object's damage level changes.
   if (%delta > 0 && %obj.getState() !$= "Dead") {

      // Increment the flash based on the amount.
      %flash = %obj.getDamageFlash() + ((%delta / %this.maxDamage) * 2);
      if (%flash > 0.75)
         %flash = 0.75;
      %obj.setDamageFlash(%flash);

      // If the pain is excessive, let's hear about it.
      if (%delta > 10)
         %obj.playPain();

       // <-- DS Damage Texture
       %damageLevel = %obj.getDamagePercent();
      
        // Change texture to reflect the damage
        for(%i = 2; %i >= 0; %i--)
        {
            if(%damageLevel > %this.damageLevelTolerance[%i])
            {
                if(%obj.getDamageTextureLevel() != %i)
                {
                    %obj.setDamageTextureLevel(%i);
                }
                break;
            }
        }
        // <-- DS Damage Texture

   }
}


I hope that is all. Good luck!

About the author

Recent Blogs


#1
06/15/2005 (4:34 am)
Dennis,

Can you provide either some screenshots or a video of this working?
#2
09/14/2005 (1:38 pm)
When I try to compile, I have this error.
F:\Programmation\TGE SDK\engine\ts\tsPartInstance.cc(258): error C2668: 'TSShapeInstance::MeshObjectInstance::renderDetailMap' : ambiguous call to overloaded function

I am not resolving the error.
If you an idea, please write a little message.
Thanks
#3
01/03/2007 (8:28 am)
Same problem here in 1.5 ...
'TSShapeInstance::MeshObjectInstance::renderDetailMap' : ambiguous call to overloaded function

:(

Any resolution to this? Any clues?