Page 1 of 1

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

Posted: Wed Jul 27, 2016 1:28 pm
by irei1as
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 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:
Image

With this code change the decals without base disappear:
Image

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


--Code changes--

In decalInstance.h add after

Code: Select all

      DecalData *mDataBlock;


this line:

Code: Select all

      S32 surfaceObject;



Then, also in that file, replace

Code: Select all

      DecalInstance() : mId(-1) {}   


with

Code: Select all

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




In projectile.cpp find:

Code: Select all

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


And replace it with:

Code: Select all

      // 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:

Code: Select all

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


And add after that:

Code: Select all

         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

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

Posted: Wed Jul 27, 2016 5:10 pm
by rlranft
Hmm, that's a good question - I thought these decals were handled client-side, but in source it references gDecalManager so perhaps these are server-side and replicated.... <shrug>

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

Posted: Thu Jul 28, 2016 1:50 am
by Azaezel

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

Posted: Thu Jul 28, 2016 2:53 pm
by flysouth
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?

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

Posted: Thu Jul 28, 2016 2:57 pm
by Azaezel
already in. that was pointing at the area where client replication occurs.

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

Posted: Fri Jul 29, 2016 12:00 pm
by irei1as
flysouth wrote:Do fixes like this automatically get put in to future engine releases?

The fix @
User avatar
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.

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

Posted: Fri Jul 29, 2016 4:22 pm
by Azaezel
@
User avatar
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.

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

Posted: Fri Jul 29, 2016 11:55 pm
by flysouth
@
User avatar
Azaezel

already in. that was pointing at the area where client replication occurs.

are you saying the decalType is already in shapebase? if so how do you access it?

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

Posted: Sun Mar 19, 2017 11:52 pm
by marauder2k9
do u think this could be modified to have a decal follow the movement of an object?

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

Posted: Tue Mar 21, 2017 5:39 pm
by irei1as
marauder2k9 wrote: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.

Code: Select all

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);