Jump to content

[C++]Bullet decals disappear if the base is destroyed


irei1as
 Share

Recommended Posts

Small code change to make the decals from bullet shots to dissapear if the object under it dissapears (or moves away or the shape changes and under the shots there is nothing anymore).

I'm not sure if it works for multiplayer and it may be heavy on resources if there are a lot of decals active.


(Related to http://forums.torque3d.org/viewtopic.php?f=12&t=733 )


Example_ A Red cube becomes a smaller green shape after a few bullets impact.

Before the code change some decals keep hanging:

http://i.imgur.com/RoWzqdB.png


With this code change the decals without base disappear:

http://i.imgur.com/XkkwlBR.png


(Note: The decals need to have lifetime. Permanent decals keep hanging.)



--Code changes--


In decalInstance.h add after

 

      DecalData *mDataBlock;

 

this line:

 

      S32 surfaceObject;

 


Then, also in that file, replace

 

	   DecalInstance() : mId(-1) {}   

 

with

 

	   DecalInstance() : mId(-1), surfaceObject(0) {}   

 



In projectile.cpp find:

 

      // Client (impact) decal.
     if ( mDataBlock->decal )     
        gDecalManager->addDecal(p, n, 0.0f, mDataBlock->decal);


And replace it with:

 

      // Client (impact) decal.
     DecalInstance * decalReturn = NULL;
     if ( mDataBlock->decal )     
        decalReturn = gDecalManager->addDecal(p, n, 0.0f, mDataBlock->decal);
     if(decalReturn)
     {
        RayInfo rInfo;
        Point3F oldPosition = p;
        Point3F newPosition = p - (n*0.05);
        // Raycast the abstract PhysicsWorld if a PhysicsPlugin exists.
        bool hit = false;
        //disableCollision();
        //let's ignore bullet physics and go the poor castRay
        hit = gClientContainer.castRay(oldPosition, newPosition, csmDynamicCollisionMask | csmStaticCollisionMask, &rInfo);
        //enableCollision();
        //if(rInfo.object has some quality that enables this check) {
           if(hit)
              decalReturn->surfaceObject = (rInfo.object)->getId(); //else, surfaceObject keeps being 0
        //} ----- closing of  if(rInfo.object has some quality...)
     }


---------------------------------


In decalManager.cpp find:

            if ( dinst->mVisibility <= 0.0f )
           {
              mDecalQueue.erase_fast( i );
              removeDecal( dinst );               
              i--;
              continue;
           }
        }


And add after that:

         if(dinst->surfaceObject)
        {
           if(!Sim::findObject(dinst->surfaceObject))
           {
              //the object that was under the decal does not exist anymore
              mDecalQueue.erase_fast( i );
              removeDecal( dinst );               
              i--;
              continue;
           }
           RayInfo rInfo;
           Point3F oldPosition = dinst->mPosition;
           Point3F newPosition = dinst->mPosition - (dinst->mNormal*0.05);
           bool hit = false;
           //disableCollision();
           //let's ignore bullet physics and go the poor castRay in the client
           hit = gClientContainer.castRay(oldPosition, newPosition, (PlayerObjectType | VehicleObjectType) | (TerrainObjectType | StaticShapeObjectType), &rInfo);
           //enableCollision();
           if(!hit || ((rInfo.object)->getId() != dinst->surfaceObject))
           {
              //the object that was under the decal moved or transformed and the decal is in the air
              mDecalQueue.erase_fast( i );
              removeDecal( dinst );               
              i--;
              continue;
           }
        }

 

They should end as:

source\T3D\decal\decalInstance.h : http://pastebin.com/43QiN2df

source\T3D\projectile.cpp : http://pastebin.com/B170LDAm

source\T3D\decal\decalManager.cpp : http://pastebin.com/r1U5fJ5F

Edited by irei1as
Link to comment
Share on other sites

Thanks for this speedy fix, although I think that it would also be good if ShapeBase also had a decalType like TSStatic so that one could decide a decal type if any. Then if it was set to "none" a decal wou;d never be placed on it.

Do fixes like this automatically get put in to future engine releases?

Link to comment
Share on other sites

Do fixes like this automatically get put in to future engine releases?

The fix @Azaezel points is already in, of course, but if you mean this resource... I don't think it's all-purpose enough to be included, it's kinda heavy with all those castRay and I'm not sure if it's 100% bug-free.

You really should fully test it before you add it (specially multiplayer if you plan to use it with that).


But, hey, if enough people check it and they think it's worth it I'm ok with a pull request to add it to the main code.



As side note, let me add a few images to the first post so it's a bit clearer what the code does.

Link to comment
Share on other sites

@irei1as could see at least checking if surfaceObject still exists if you'd wanna throw over a minimalist interpretation without the castrays. you're right about tree-searching for a lot of decals potentially getting a bit hairy, but i'd think a simple 'this still valid' test would be ok preformance wise.

Link to comment
Share on other sites

  • 7 months later...
do u think this could be modified to have a decal follow the movement of an object?

 

If the object has no internal animations it's very easy, like a static object moving with a tween.

Add the matrix transform of the parent object (the object receiving the decal) as a variable of the decal. Then if the object position changes (you have the id of the object to check) you make a transform of the decal according to that.



The problem is if the object has animations, like the soldier moving his feet or arms.

That's because it's not easy to know where in the geometry the hit will be in any other frame.

Checking how the nodes moves may be a starting point but that needs a C++ change for the nodes to show the transform in real time.


This is what I have related to this for the 3.8 version. Sadly I can't use the new code for the newest version.

Inside source/T3D/shapeBase.h add before the end of the definition of class ShapeBase:

public:
  MatrixF getNodeTransformN(const String &nodeName);
  MatrixF getNodeTransform(const S32 nodeIdx);


Inside source/T3D/shapeBase.cpp just at the end:


MatrixF ShapeBase::getNodeTransformN(const String &nodeName)  
{  
  S32 nodeIdx = mShapeInstance->getShape()->findNode(nodeName);  

  return getNodeTransform(nodeIdx);  
}  

MatrixF ShapeBase::getNodeTransform(const S32 nodeIdx)  
{  
  MatrixF returnValue = MatrixF::Identity;
  if(nodeIdx != -1)  
  {  
     if (isServerObject() && mShapeInstance)  
        mShapeInstance->animateNodeSubtrees(true);  

     returnValue = mShapeInstance->mNodeTransforms[nodeIdx];
  }  

  MatrixF objectTransform = getTransform();

  Point3F nodeObjPos = returnValue.getPosition();
  nodeObjPos.convolve( getScale() );
  returnValue.setPosition(nodeObjPos);

  returnValue.mulL(objectTransform);

  return returnValue;
}  

DefineEngineMethod( ShapeBase, getNodeTransform, TransformF, (const char* nodeName),,
  "Get the transform of a named node in the shape.\n"
  "@param nodeName Name of the node to check.\n" 
  "@return The current transform of the node.\n" )
{
  return TransformF(object->getNodeTransformN(nodeName));  
}

---------------------------------------------------------------------------------------------------------------------


In source\T3D\shapeImage.cpp look inside of
void ShapeBase::getMountTransform( S32 index, const MatrixF &xfm, MatrixF *outMat )
for
        MatrixF mountTransform = mShapeInstance->mNodeTransforms[ni];
And add these lines before:

        if (isServerObject() && mShapeInstance)  
           mShapeInstance->animateNodeSubtrees(true);  

Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

 Share

×
×
  • Create New...