Page 3 of 4

Posted: Fri Jun 11, 2010 11:10 am
by Scarabol
I changed my driver to OpenGl and it works now.

I use it to display a shield around the player and all enemies. When i shot at them you can see the bullet hitting the surface of the shield, but the bullet has the same effect on the players shield when leaving it.

How can i change the code to display only shots going into the shield and not going out?

MfG
Scarabol

Posted: Fri Jun 11, 2010 11:48 am
by freetimecoder
ARB is OpenGL too I think.
Adding a global impact means you have your node and add a point on the shields surface. The shader however requires the coordinats to be in the shield node's space. So the point's position is transformed to local space. Using localimpact means you know the local space of the node and add the point in local space.

For the bullet: Check wether the bullets trajectory is towards or out of the shield and add only the impacts you want. The collision detection of the sample does not differ between in or outgoing shots, the method simply returns the first collision point with the shield.

greetings

Posted: Mon Jun 14, 2010 7:03 pm
by Scarabol
Hi,

whats to do to use this with Direct3D9?

MfG
Scarabol

Posted: Tue Jun 15, 2010 7:41 pm
by Scarabol
Back to outgoing shots, i think it is the task for the shield manager because it should compare the normal of the selected triangle with the direction of the ray.

MfG
Scarabol

Posted: Tue Jun 15, 2010 8:40 pm
by freetimecoder
To use this with DirectX you have to write a shader in a directX shader language and add it to the shieldmanager constructor.

As for the direction of the shots, the shieldmanager is merely to display shields and impacts. It is like the scenemanager and 'basic collision' there is something implemented and if you want more advanced/accurate detection you are welcomed to do it yourself ;)

Anyway it would not be so hard to change that. You could either prevent the collisiondetection of outgoing bullet and shield in your game engine in the first place or rewrite the addImpact method like this:

Code: Select all

core::vector3df CShieldManager::addImpact(const scene::ISceneNode *node, const core::line3df ray, const f32 radius, const u32 duration, const video::SColorf color){
    //Check if node pointer is given, otherwise the collision point routine will crash
    if(!node)
        return ray.end;

    //Check if endpoint is closer to shield center than start point
    if(node->getAbsolutePosition().getDistanceFrom(ray.start) > node->getAbsolutePosition().getDistanceFrom(ray.end)){
	    //Check for intersection
	    core::vector3df colPoint;
	    core::triangle3df colTris;
	    const scene::ISceneNode* outNode;
	    if(smgr->getSceneCollisionManager()->getCollisionPoint(ray,
		    node->getTriangleSelector(), colPoint,
		    colTris, outNode))
	    {
		//Intersection found
		//Transform position to local space
		core::vector3df tmpPoint = core::vector3df(colPoint);
		core::matrix4 trans = node->getAbsoluteTransformation();
		trans.makeInverse();
		trans.transformVect(colPoint);
		//Add impact
		addLocalImpact(node,colPoint,radius,duration,color);
		return tmpPoint;
	    }
    }
    //No intersection
    return ray.end;
} 
You can of course instead compare the normals.

For round shields this should work, for complex shields with edges or something it might not be accurate enough. Another point, why this detection is not included and should be customized by the user.

greetings

Posted: Wed Jun 16, 2010 12:30 am
by Scarabol
Thanks for your reply, i made it this way:

Code: Select all

/*...*/
    if(smgr->getSceneCollisionManager()->getCollisionPoint(ray,
            node->getTriangleSelector(), colPoint,
            colTris, outNode))
    {
		core::vector3df vec1 = colTris.getNormal(), vec2 = ray.getVector();
		f32 angle = acos(vec1.dotProduct(vec2) * core::reciprocal_squareroot(vec1.getLengthSQ() * vec2.getLengthSQ()));
		angle *= 180 / core::PI; // this could be better i know, just for testing purpose
		if (angle >= 90)
		{
/*...*/
Why do you think this would not work with complex mesh?

MfG
Scarabol

Posted: Wed Jun 16, 2010 7:09 am
by freetimecoder
Sorry, wrote this the wrong way around xD
I meant the start/end distance to center method would not work for complex meshes.

greetings

Posted: Wed Jun 16, 2010 10:46 am
by Scarabol
Here is a screenshot of my current projekt state with your shield effects:
Image

Everytime i use another mesh than ISphereMesh i get these faults u can see on the screenshot. The impact are not displayed on the mesh but next to it.

Im using your original source and my shieldnode is the IAnimatedMeshSceneNode you can see on the screenshot (gray one)

MfG
Scarabol

Posted: Wed Jun 16, 2010 11:11 am
by Virion
nice stuff mate. i'm thinking of using this effect in my project too. :D

Posted: Wed Jun 16, 2010 12:01 pm
by freetimecoder
Hm looks to me like the impacts would be displayed where the bullets hit, just that the shield itself has a wrong position. How do you create the shield node?

Did you try using a non transparent impact texture to see the complete shield for debugging?

greetings

Posted: Thu Jun 17, 2010 3:27 pm
by Scarabol
freetimecoder wrote:Hm looks to me like the impacts would be displayed where the bullets hit, just that the shield itself has a wrong position. How do you create the shield node?

Code: Select all

	_shieldnode = smgr->getmesh("station_shield.x");
	_shieldnode->setParent(this->getnode());
	_shieldnode->setMaterialFlag(EMF_BACK_FACE_CULLING, false);
	_shieldnode->setVisible(true);
    scene::ITriangleSelector *selector = _gm->getsmgr()->createTriangleSelector(_shieldnode->getMesh(), _shieldnode);
    _shieldnode->setTriangleSelector(selector);
    selector->drop();
	_shieldnode->setMaterialTexture(0, _gm->getdriver()->getTexture("../data/shield_tex.png"));
	_shieldnode->setMaterialTexture(1, _gm->getdriver()->getTexture("../data/gradient.png"));
	_gm->getshieldmanager()->addShield(_shieldnode);
Just like your code example with backface culling ect. Maybe transform to local space is wrong?
Console says no errors everything is loaded in right way.
freetimecoder wrote:Did you try using a non transparent impact texture to see the complete shield for debugging?
The gray one is my non transparent shield node :-)

MfG
Scarabol

Posted: Thu Jun 17, 2010 6:53 pm
by freetimecoder
Sure this is the code you use?

Code: Select all

   _shieldnode = smgr->getmesh("station_shield.x"); 
Anyway, have you tried addGlobal impact with a point on the shieldnode's surface? Are those displayed correctly?

I still have no real clue of what could cause this :?
The sample's shields use parents, too and the transform works there.

greetings

Posted: Tue Jul 20, 2010 10:46 pm
by B@z
could we get a chance to use it with dx please? :3
i tried to translate it to HLSL, but since i have no knowledge of shader programming, couldnt make it.

So i'd be very glad if someone could translate it for me :3

Posted: Thu Jul 22, 2010 6:00 pm
by Dave the Idiot
Hi

I have been messing with the code so it isn't exactly the same but I have almost produced a HLSL version. The main problem with the HLSL version is the impacts start off large and shrink. This is the first time I have messed with HLSL so if anyone wants to point out my errors feel free.


[code]

varying vec3 vertpos;

void main(void)
{
vertpos = gl_Vertex.xyz;
gl_TexCoord[0] = gl_MultiTexCoord0;
gl_Position = ftransform();
}

//Fragment Shader

uniform float radius;
uniform vec4 color;
uniform vec3 current_position;
varying vec3 vertpos;

void main(void)
{
vec3 dif = vertpos - current_position;
float dist = dif.x*dif.x + dif.y*dif.y + dif.z*dif.z;
float intensity=1/dist*radius*0.01; if(intensity>0.9)
intensity=0.9;
if(intensity<0)
intensity=0;

vec4 final_color = color * intensity;
gl_FragColor=final_color;
}
";

[/code]


becomes

[code]

float4x4 mWorld;
float4x4 mView;
float4x4 mProj;
float4x4 worldViewProjection;

struct VS_OUTPUT {
float4 Pos: POSITION;
float2 TexCoords: TEXCOORD0;
float4 vPos: TEXCOORD1;
};

VS_OUTPUT main(float4 Pos: POSITION,
float2 TexCoords : TEXCOORD0)
{
VS_OUTPUT output;
output.vPos = Pos;
worldViewProjection = mul(mul(mWorld, mView), mProj);
output.Pos = mul(Pos, worldViewProjection);
output.TexCoords = TexCoords;
return output;
}

float radius;
float4 color;
float3 current_position;



float4 main(float2 TexCoords: TEXCOORD0, float4 vPos: TEXCOORD1) : COLOR
{
float3 dif;
dif.x = vPos.x;
dif.y = vPos.y;
dif.z = vPos.z;
dif = dif - current_position;
float dist = dif.x*dif.x + dif.y*dif.y + dif.z*dif.z;

float intensity=1/((dist*radius*0.01));
if(intensity>0.9)
intensity=0.9;
if(intensity<0)
intensity=0;

float4 final_color = color * intensity;
return final_color;
}






[/code]

Posted: Thu Jul 22, 2010 6:57 pm
by B@z
omg nice!

tho, i found some misses, but at least i could start from somewhere!

here is the code:

vertex:

Code: Select all

float4x4 worldViewProjection;

struct VS_OUTPUT {
float4 Pos:	 POSITION;
float2 TexCoords:	TEXCOORD0;
float4 vPos:	 TEXCOORD1;
};

VS_OUTPUT main(float4 Pos: POSITION,
float2 TexCoords : TEXCOORD0)
{
VS_OUTPUT output;
output.vPos = Pos;
output.Pos = mul(Pos, worldViewProjection);
output.TexCoords = TexCoords;
return output;
}
fragment:

Code: Select all

float radius;
float4 color;
float3 current_position;

sampler2D ColorMap : register(s1); 
sampler2D GradientTexture : register(s2);

float4 main(float2 TexCoords:	TEXCOORD0, float4 vPos:	TEXCOORD1) : COLOR 
{
float3 dif = vPos.xyz;
dif = dif - current_position;
float dist = dif.x*dif.x + dif.y*dif.y + dif.z*dif.z;

float intensity=1/dist*radius*0.01;
if(intensity>0.9)
intensity=0.9;
if(intensity<0)
intensity=0;

float4 diffuse = tex2D(ColorMap, TexCoords);
float4 gradient = tex2D(GradientTexture, float2(intensity,1));

float4 final_color = gradient * diffuse * intensity * color;
return final_color;
}
and at onsetconstaints:

Code: Select all

//This is called for each impact render
void CShieldManager::OnSetConstants(video::IMaterialRendererServices* services, s32 userData)
{
	video::IVideoDriver* driver = services->getVideoDriver();
	core::matrix4 worldViewProj; 
	worldViewProj = driver->getTransform(video::ETS_PROJECTION); 
	worldViewProj *= driver->getTransform(video::ETS_VIEW); 
	worldViewProj *= driver->getTransform(video::ETS_WORLD); 
	services->setVertexShaderConstant("worldViewProjection", worldViewProj.pointer(), 16); 

	services->setPixelShaderConstant("current_position", (float*)(&tmp_position ), 3);
    services->setPixelShaderConstant("radius", (float*)(&tmp_radius ), 1);
    services->setPixelShaderConstant("color", (float*)(&tmp_color ), 4);
}
it works good, only one bug:
http://blud.freeiz.com/up/glsl.jpg
http://blud.freeiz.com/up/hlsl.jpg

as u see, on the glsl picture, its nice, but the hlsl is pretty pixel'ish
how can i solve it?