I'll scratch your back you scratch mine?

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.
kendric
Posts: 71
Joined: Tue May 29, 2007 9:05 pm

I'll scratch your back you scratch mine?

Post by kendric »

I reworked the Armen138 decal system which was working, then broken with a version of irrlicht and then fixed, but then the link went dead.

Feel free to use it. It works great on level geometry. However when I modified it to work on moving things, it is close, but not quite right. So if you want to use this and you know what I did wrong let me know. I will put a comment on the places where I added the code to handle being on a non world object.

Note if you want it to work only on world geometry simply remove the subtraction in the constructor that is applied to pointA,B,C and the posA,B,C and it works great.

You need the namespaces(video etc) declared in your projects header somewhere, either that or add them back in.

DecalSceneNode.cpp

#include "StdAfx.h"
#include "DecalSceneNode.h"
/*
bullethole/decal class
by Armen138

before creating an instance of this class, i assume you got:
1. the triangle you hit with your weapon
2. the coordinates(intersection point) you hit the triangle at
3. the texture you want to display on the decal
4. the size you want the bullethole to be(you'll have to experiment a little with this one)

these are the last 4 arguments for the constructor.

this will create a square decal displaying your texture on the wall you hit
with a weapon shooting in a straight line.
*/

DecalSceneNode::DecalSceneNode(ISceneNode* parent, ISceneManager* mgr, triangle3df tri, vector3df intersection, ITexture* image, float size): ISceneNode(parent, mgr, 0)
{
time(&c_time);
lifeSpan=0;
pointA=tri.pointA;
pointA-=parent->getPosition();// i added this to shift it to be relative
pointB=tri.pointB;
pointB-=parent->getPosition();//and i added this
pointC=tri.pointC;
pointC-=parent->getPosition();//and this
posA=intersection.X-parent->getPosition().X;//and this -parent...
posB=intersection.Y-parent->getPosition().Y;//and this -parent...
posC=intersection.Z-parent->getPosition().Z;//and this -parent...
trinormal=tri.getNormal();
dotcorrection=1;


Material.Wireframe = false;
Material.Lighting = false;

this->setMaterialType(EMT_TRANSPARENT_ALPHA_CHANNEL);
this->setMaterialFlag(EMF_LIGHTING, false);
this->setMaterialTexture(0, image );
basesize=size/2;


trinormal=trinormal.normalize();
line3d<f32> line1(pointA, pointB);
vector3df v1 = line1.getVector().normalize();
vector3df v2 = line1.getClosestPoint( pointC );
line3d<f32> line2(v2,pointC);
vector3df v3 = line2.getVector().normalize();

vector3df squarepA=(v1*-basesize)+trinormal*dotcorrection+(v3*-basesize);
vector3df squarepB=squarepA+(v1*basesize*2);
vector3df squarepC=squarepA+(v1*basesize*2)+(v3*basesize*2);
vector3df squarepD=squarepA+(v3*basesize*2);


squarepA=squarepA+core::vector3df(posA,posB,posC);
squarepB=squarepB+core::vector3df(posA,posB,posC);
squarepC=squarepC+core::vector3df(posA,posB,posC);
squarepD=squarepD+core::vector3df(posA,posB,posC);

Vertices[0] = S3DVertex(squarepA.X,squarepA.Y,squarepA.Z, 1,0,0,video::SColor(255,255,255,255),1,0);
Vertices[1] = S3DVertex(squarepB.X,squarepB.Y,squarepB.Z, 1,0,0,video::SColor(255,255,255,255),1,1);
Vertices[2] = S3DVertex(squarepC.X,squarepC.Y,squarepC.Z, 1,0,0,video::SColor(255,255,255,255),0,1);
Vertices[3] = S3DVertex(squarepD.X,squarepD.Y,squarepD.Z, 1,0,0,video::SColor(255,255,255,255),0,0);


Box.reset(Vertices[0].Pos);
for (s32 i=1; i<4; ++i)
Box.addInternalPoint(Vertices.Pos);

}


void DecalSceneNode::setLifeSpan(double seconds){
lifeSpan=seconds;
}

float DecalSceneNode::getSize(){
return basesize*2;
}
void DecalSceneNode::OnRegisterSceneNode()
{
if(lifeSpan>0){if(difftime(time(NULL),c_time) > lifeSpan)SceneManager->addToDeletionQueue(this);}
if (IsVisible)
SceneManager->registerNodeForRendering(this);
ISceneNode::OnRegisterSceneNode();
}

void DecalSceneNode::render()
{
u16 indices[] = { 0,1,2, 0,2,3};
IVideoDriver* driver = SceneManager->getVideoDriver();

driver->setMaterial(Material);
driver->setTransform(ETS_WORLD, AbsoluteTransformation);
driver->drawIndexedTriangleList(&Vertices[0], 4, &indices[0], 2);
}

const aabbox3d<f32>& DecalSceneNode::getBoundingBox() const
{
return Box;
}

u32 DecalSceneNode::getMaterialCount()
{
return 1;
}

SMaterial& DecalSceneNode::getMaterial(u32 i)
{
return Material;
}

Here is the .h

#pragma once

class DecalSceneNode : public ISceneNode
{
protected:
aabbox3d<f32> Box;
S3DVertex Vertices[4];
SMaterial Material;

public:
DecalSceneNode(ISceneNode* parent, ISceneManager* mgr, triangle3df tri, vector3df intersection, ITexture* image,float size);
vector3df pointA;
vector3df pointB;
vector3df pointC;
float posA;
float posB;
float posC;
vector3df trinormal;
float basesize;

float dotcorrection;
//IVideoDriver* driver;

line3d<f32> line1;
vector3df v1;
vector3df v2;
line3d<f32> line2;
vector3df v3;

vector3df squarepA;
vector3df squarepB;
vector3df squarepC;
vector3df squarepD;

time_t c_time;
time_t d_time;
double lifeSpan;

void setLifeSpan(double seconds);
float getSize();
void OnRegisterSceneNode();

void render();


const aabbox3d<f32>& getBoundingBox() const;

virtual u32 getMaterialCount();

virtual SMaterial& getMaterial(u32 i);

};
kendric
Posts: 71
Joined: Tue May 29, 2007 9:05 pm

Post by kendric »

Oh i meant to say whats the problem :)

It works sorta, but the bullet holes are applied at the angle of impact, or I don't have their rotation quite right or something, and not along the surface of the box\whatever they are on. So sometimes they look ok, other times they are sticking out at an angle almost like a shuriken embeded into a wall.
And directly related to this, you somtimes don't see them at all, which I assume means they are backwards and thus have no texture, or totally inside the box or something.
Dorth
Posts: 931
Joined: Sat May 26, 2007 11:03 pm

Post by Dorth »

Why don't you use the impact triangle's plane/normal to set your angle?
kendric
Posts: 71
Joined: Tue May 29, 2007 9:05 pm

Post by kendric »

Isn't that what this is?

trinormal=tri.getNormal();
Dorth
Posts: 931
Joined: Sat May 26, 2007 11:03 pm

Post by Dorth »

Ah, yes, nvm that, but what is that dotcorrection your timing it with? (BTW, extremely late here, haven't even ran your code, just spouting ideas.) If you got the triangle, why not do

vector3df trinormal=tri.getNormal();
vector3df LineBA = tri.PointA.getPosition() (getAbsolutePosition?) - tri.PointB.getPosition() ;
vector3df LineBACenter = tri.PointB.getPosition() + (LineBA * 0.5f);
vector3df LineCToBAC = LineBACenter - tri.PointC.getPosition() ;
vector3df CenterTri = tri.PointC.getPosition() + (LineCToBAC * 0.5f);

(for this part I'm assuming the bullet is round or so, so I just place the square on the plane)

vector3df NormX = LineBACenter.normalize();
vector3df NormY = trinormal.cross(NormX);

f32 ModSquareSize = 1.0f; //(Place your value here to modify the size of the square)

f32 Displacement = 0.00001f; // (How far above the triangle the square will be)

vector3df DisNormal = ( Displacement * trinormal);

vector3df squarepA = CenterTri + (NormX * ModSquareSize ) + DisNormal;
vector3df squarepB = CenterTri + (NormY * ModSquareSize ) + DisNormal;
vector3df squarepC = CenterTri - (NormX * ModSquareSize ) + DisNormal;
vector3df squarepD = CenterTri - (NormY * ModSquareSize ) + DisNormal;


Hope this help, too tired anyway, have fun :)
kendric
Posts: 71
Joined: Tue May 29, 2007 9:05 pm

Post by kendric »

Just to give credit first, this is not my code mostly, its Armen's

So I am not an expert in vector math but I think I see how what your saying works. I tried it out and it ends up giving you long line across the entire map :)

I may need to tweak this at some point so it uses intersection point, it shouldn't be placed on the triangle, it uses the triangle for angle of the image, but the center should be at intersection point.

Here is the code as i tweaked it to make it compile.

//Get the relative position of this triangle
pointA=tri.pointA;
pointA-=parent->getPosition();
pointB=tri.pointB;
pointB-=parent->getPosition();
pointC=tri.pointC;
pointC-=parent->getPosition();



vector3df trinormal=tri.getNormal();
vector3df LineBA = pointA- pointB;
vector3df LineBACenter = pointB + (LineBA * 0.5f);
vector3df LineCToBAC = LineBACenter - pointC;
vector3df CenterTri = pointC + (LineCToBAC * 0.5f);

vector3df NormX = LineBACenter.normalize();
vector3df NormY = trinormal.crossProduct(NormX);

f32 ModSquareSize = 1.0f; //(Place your value here to modify the size of the square)

f32 Displacement = 0.00001f; // (How far above the triangle the square will be)

vector3df DisNormal = ( Displacement * trinormal);
vector3df squarepA = CenterTri + (NormX * ModSquareSize ) + DisNormal;
vector3df squarepB = CenterTri + (NormY * ModSquareSize ) + DisNormal;
vector3df squarepC = CenterTri - (NormX * ModSquareSize ) + DisNormal;
vector3df squarepD = CenterTri - (NormY * ModSquareSize ) + DisNormal;


Here are some values i snagged from the debugger during a test of it.

tri= {pointA={X=-17.326456 Y=70.787727 Z=24.984577 } pointB={X=21.987974 Y=70.782410 Z=16.356829 } pointC={X=21.937763 Y=30.532959 Z=16.152842 } }

NormX {X=-0.14971253 Y=0.71525240 Z=-0.68264204 }
NormY {X=1126.0341 Y=-0.15219116 Z=-247.11380 }

LineBACenter {X=-0.14971253 Y=0.71525240 Z=-0.68264204 }
LineCToBAC {X=-19.607004 Y=40.252110 Z=4.5178623 }
LineBA {X=-39.314430 Y=0.0053176880 Z=8.6277485 }

DisNormal {X=-0.0034726104 Y=8.4528503e-005 Z=-0.015823845 }

CenterTri {X=5.6483049 Y=-0.27458000 Z=-21.205322 }

trinormal {X=-347.26105 Y=8.4528503 Z=-1582.3845 }

squarepA {X=5.4951196 Y=0.44075692 Z=-21.903788 }
squarepB {X=1131.6790 Y=-0.42668664 Z=-268.33496 }
squarepC {X=5.7945447 Y=-0.98974788 Z=-20.538504 }
squarepD {X=-1120.3892 Y=-0.12230431 Z=225.89265 }


It looks like NormY is the problem. I am not sure what it shoudl be at this time. I will keep poking at it.

I am also thinking at the end I should replace tricenter with intersection when calculating squarepA-D. I will repost the code cleaned up once I get this working.
kendric
Posts: 71
Joined: Tue May 29, 2007 9:05 pm

Post by kendric »

Doing a normalize on NormY gives more normal results but still got an issue to figure out.
Dorth
Posts: 931
Joined: Sat May 26, 2007 11:03 pm

Post by Dorth »

Hmm, yeah, sorry 'bout those 2 things, did I mention it was 2 am? :P
Well, tell more about the issue left, I'll see what I can do :)
kendric
Posts: 71
Joined: Tue May 29, 2007 9:05 pm

Post by kendric »

Well it might be something unrelated. Its basically doing what it did with my old code, which is having them not being perfectly lined up with the surface they are on. They go in at random angles again. So it may be something with how they are being attached to another scene node which has a rotation or some such. I imagine the world map has no rotation etc.
Dorth
Posts: 931
Joined: Sat May 26, 2007 11:03 pm

Post by Dorth »

Ahah! Yes. Now I remember... I did not take into consideration whether you were attaching it or not (didn't read the code, right ;) ) which is more than likely your problem. 'k, so how can we fix this... Well, easiest way to do it is somehow find the bone weight on the three vertices making the original triangles, then applying that on the new triangle. PIECE OF CAKE! Kidding ;) Well, I need to find something like that for an effect in the game I'm working on anyway, so if I find anything, I'll post. Second solution, which is risky but might work (though only with low poly models or high framerate) is each frame, calculating the moment of the model, from the vector3df representing the center of the triangle, calculate a new one (applying rotation, movement, scaling, etc.) then, try and collide that point toward the inverse of the normal previously used (after rotating it if the model rotated). Hope your following.

Basically:
Model A
Center of Triangle B
Normal of Triangle C
A', B' and C' represent last frame position

B = B' + (A - A') (including scaling and rotation) + C' * distance we want to be safe.
C = C' modified with rotation of model.

Now cast a ray collision from B toward -C (the inverted normal) * A number bigger than the distance you moved your triangle away from the original collision triangle, 1000 if you so want.

Apply new triangle to new collision found.

Now I know they are MANY weaknesses with that. First one is the impact even if on the same triangle won't be on the same point. Well then, we just need to remember where the Impact was in regard to the triangle. I'll leave it to you to find this out. Now second big one, what if the model is animated (well that's the assumption between recalculating the impact anyway). That's why I said we need to have either low poly or high framerate or better yet, both, that way it's pretty risk free that the same triangle will be selected.

Ah but what happen if another model comes in-between the triangle and the collision triangle. Then you should collide only against the same node than the one you previously impacted.

Hope this'll help, if not I'll give it more thoughts later...
kendric
Posts: 71
Joined: Tue May 29, 2007 9:05 pm

Post by kendric »

I think were barking up the wrong tree. The bullet holes move and rotate with the thing they are attached to just fine. So the only issue is the initial attach angle. Once that is fixed they will move fluidly with the rest of it. I am thinking I need to set the rotation of the decal scene node to equal the models or something. i am gonna try a few of those things today and I will let you know what happens.
Dorth
Posts: 931
Joined: Sat May 26, 2007 11:03 pm

Post by Dorth »

Al'right, but I don't see how it would be possible for the triangle to properly follow, let's say, an animated arm. Anyhow, screens of what you mean would help ;)
kendric
Posts: 71
Joined: Tue May 29, 2007 9:05 pm

Post by kendric »

I did some testing by having the decals not be inside the box to see them better, but still attached to the box(their parent scene node).

If i move the mouse left to right as i fire, where the bullet hole lands shifts up and down,and if i go up and down with the mouse it shifts left and right. So it has to be a rotation issue. I am messing with things like setRotation(parent->getRotation()) I will let you know if i figure it out.
kendric
Posts: 71
Joined: Tue May 29, 2007 9:05 pm

Post by kendric »

I also confirmed that the triangle is in the right place by having it draw one on screen where i click. So it has to be some transform issue thats rotating these bullet holes around the object they are on and not putting them where the triangle is.

So I did some further testing. If i make these things's parents the root scene node, and i compeltely remove the box from impacting their location, they appear in the right place but are still at the wrong angle slightly. They are slightly tilted. So it must be something wrong in the base code. I will repost the relavent part here as it stands:

**Edit**
I put the old code back to test some stuff. It works on walls or objects as long as they don't move from when you clicked. this leads me to believe that the rotation of the scene node is not effecting the rendering of vertexes in the triangle render code. This means that I need to rotate the vertexes each time i render them. I am going to see if I know how to do that. If you happen to have code to rotate a vertex given a vector3df rotation value be sure to post it ;)
*******


vector3df pointA, pointB, pointC;
vector3df trinormal,squarepA,squarepB,squarepC, squarepD;
time(&c_time);
lifeSpan=0;
pointA=tri.pointA;
pointB=tri.pointB;
pointC=tri.pointC;

Material.Wireframe = false;
Material.Lighting = false;

this->setMaterialType(EMT_TRANSPARENT_ALPHA_CHANNEL);
this->setMaterialFlag(EMF_LIGHTING, false);
this->setMaterialTexture(0, image );
basesize=size/2;

trinormal=tri.getNormal();
trinormal.normalize();
vector3df LineBA = pointA- pointB;
vector3df LineBACenter = pointB + (LineBA * 0.5f);
vector3df LineCToBAC = LineBACenter - pointC;
vector3df CenterTri = pointC + (LineCToBAC * 0.5f);

vector3df NormX = LineBACenter.normalize();
vector3df NormY = trinormal.crossProduct(NormX);

f32 ModSquareSize = size; //(Place your value here to modify the size of the square)
f32 Displacement = -0.001f; // (How far above the triangle the square will be)

vector3df DisNormal = ( Displacement * trinormal);

squarepA = intersection + (NormX * ModSquareSize );// + DisNormal;
squarepB = intersection + (NormY * ModSquareSize );// + DisNormal;
squarepC = intersection - (NormX * ModSquareSize );// + DisNormal;
squarepD = intersection - (NormY * ModSquareSize );// + DisNormal;

Vertices[0] = S3DVertex(squarepA.X,squarepA.Y,squarepA.Z, 1,0,0,video::SColor(255,255,255,255),1,0);
Vertices[1] = S3DVertex(squarepB.X,squarepB.Y,squarepB.Z, 1,0,0,video::SColor(255,255,255,255),1,1);
Vertices[2] = S3DVertex(squarepC.X,squarepC.Y,squarepC.Z, 1,0,0,video::SColor(255,255,255,255),0,1);
Vertices[3] = S3DVertex(squarepD.X,squarepD.Y,squarepD.Z, 1,0,0,video::SColor(255,255,255,255),0,0);


Box.reset(Vertices[0].Pos);
for (s32 i=1; i<4; ++i)
Box.addInternalPoint(Vertices.Pos);


And the rendering part

driver->setTransform(ETS_WORLD, AbsoluteTransformation);
driver->drawIndexedTriangleList(&Vertices[0], 4, &indices[0], 2);
Dorth
Posts: 931
Joined: Sat May 26, 2007 11:03 pm

Post by Dorth »

Actually, rotating a vertex without a reference point would be rather useless :P
I'm moving today so I won't be of much help until at least Thursday. If you still haven't found the solution then, I'll manage to find it somehow and share it ^^ :P (we will succeed ;) )
Post Reply