I'll scratch your back you scratch mine?
Posted: Fri Jun 22, 2007 2:16 am
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);
};
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);
};