PDA

View Full Version : Drawing phasers!



JernejL
21-03-2009, 11:06 PM
Ok, for a while i have this problem with rendering scifi-like phasers for my game, the thing is, i have to use a proper texture for the ray, and it has to be aligned to always face the screen, something like a "billboard line".

http://www.furryconflict.com/tech/technopedia/technology/weapons/phaserbolt.jpg

Here is my miserable attempt.. using GLplane, i cannot figure out how to make this thing orient at the camera:
http://mathpudding.com/temp/phasers.jpg

I am looking for any sort of advice on how to do this properly, any help will be greatly appreciated. also i'm using glscene for object management so if you can figure out something that i can use from glscene it would just.. rock.

chronozphere
22-03-2009, 12:24 AM
Okay... looks like a math problem. I try to explain what i would do. No guarantees that it will work though. ???

We have a line in 3d space between vector A and B. Our camera location is given by vector C. V1, V2, V3, V4 are the four vertices that form the quad we will use to render our beam texture to (These four vectors need to be calculated).

Imagine we defined a plane that ran through the line AB and camera position C. The normal vector of this plane would be:

N = Cross_Product( A - B, A - C ).

This normal vector will always be perpendicular to the line when looking through our camera. Like this:



N
|
|__________________
A B


Now we want our quad vertices to be like this:



V1 V3
| |
|__________________|
A| |B
| |
V2 V4


This is easy:

V1 = A + N
V2 = A - N
V3 = B + N
V4 = B - N

Now you have your four vertices. Just draw a textured quad using these and you'll be all set, unless i'm missing something ofcourse. It might be desirable to Normalize N and multiply it with a certian number to change the line's "thickness", but that's up to you. ;)

Hope this helped. :)

JernejL
22-03-2009, 09:08 AM
Could i somehow calculate a matrix for that normal so i could use it with glscene? basically, set the object at beam origin, apply this matrix and the visual child object would be properly oriented along the beam direction and normal?

JSoftware
22-03-2009, 09:18 AM
What kind of matrix? A rotation matrix? Does GLScene have some sort of utility functions to convert axis-angle, quaternions or euler angles to a matrix?

JernejL
22-03-2009, 09:33 AM
What kind of matrix? A rotation matrix? Does GLScene have some sort of utility functions to convert axis-angle, quaternions or euler angles to a matrix?


I meant ordinary 4*4 transformation matrix (the rotation part mostly).
and yeah it has routines to handle quaternions and euler angles

ize
22-03-2009, 01:43 PM
Hi there. I'm still trying to work out why it has to face the camera all the time. Wouldn't that just make it appear 2D like a sprite ???

Wouldn't say your attempt was pathetic 8), You could use a gldisc at the "base" of the laser which always faces the camera to give it a sort of glare and then draw the plane as you have. You could also use a couple of glshaders to give it a glow effect.

JernejL
22-03-2009, 03:37 PM
Hi there. I'm still trying to work out why it has to face the camera all the time. Wouldn't that just make it appear 2D like a sprite ???

Wouldn't say your attempt was pathetic 8), You could use a gldisc at the "base" of the laser which always faces the camera to give it a sort of glare and then draw the plane as you have. You could also use a couple of glshaders to give it a glow effect.


Because it's a engine remake, and i need to use existing texture that look like this:

http://mathpudding.com/temp/phaser.jpg

These are then colored to match specified phaser emitter color by the engine.

Well actually, the game i'm rebuilding is even more complex (size was intentionally exaggerated to make the shape and complexity more obvious).
http://mathpudding.com/temp/phasr1.jpg

http://mathpudding.com/temp/phasershape.jpg

But i'll be happy if i can draw a quad facing the camera for now, when that works i can work on more complex shapes.

The project is opensource, and has a sourceforge project here: http://sourceforge.net/projects/st-sc

No releases yet, but i can get you a working demo if anyone is interested.

Right now my game renders these phasers with TGLPipe in a solid color, but the pipes don't have any uv mapping and cannot draw quad lines, so they are unsuitable for this use.

This is how they look with Tglpipe:
http://mathpudding.com/temp/pipephasers.jpg

ize
22-03-2009, 04:10 PM
Ah, that makes thing a bit clearer for me now. I wrote a track editor some time ago which basically used splines to generate the "path" of the track, then generated and saved it as a 3ds object. i don't know how useful that would be to you if the phasers are in constant need of updating. What performance-hit are you getting using pipes? There may be some tweaking there that incorporates uv mapping.

I'm sure the source for my track-ed is on one of my drives somewhere. If i find it, or figure out anything else i'll post it.

Those screenies look great btw :thumbsup:

User137
22-03-2009, 04:12 PM
1 solution is also to draw 2 quads instead of 1 so that they a form + sign if looked in front. I mean, if beam is directed in Z-axis, make textured quads on YZ and XZ planes... It should look ok from every angle assuming you can smooth/hide the beam ends.

Looks something like this 8)

http://i42.tinypic.com/ri9g0n.png

JernejL
22-03-2009, 06:02 PM
1 solution is also to draw 2 quads instead of 1 so that they a form + sign if looked in front. I mean, if beam is directed in Z-axis, make textured quads on YZ and XZ planes... It should look ok from every angle assuming you can smooth/hide the beam ends.

Looks something like this 8)

http://i42.tinypic.com/ri9g0n.png


That will probably be what i will have to use, unless i can make it look just like the original game (see screenshots)

Ize: generating geometry along path isn't hard, the hard part is getting it facing the camera.

JernejL
22-03-2009, 06:39 PM
Those screenies look great btw :thumbsup:


only the last screenshot was of my game, others were from game i'm remaking.

ize
23-03-2009, 11:02 AM
Here's a quick and dirty hack i wrote you might be able to use. You'll need to add a TGLDirectOpenGL component to your GLScene as well as adding OpenGL1X to your uses list. It's compiled with Delphi 2009, but i don't think there's any difference in code if you're using another version.


{ Draws the Phase }
procedure Phase(Sides: Byte;Rad: Single;Mat: TGLLibMaterial;
const Verts: array of TVector;var rci: TRenderContextInfo);
var
fn,cv,nv,d,u,r: TVector;
Vx: array of TVector;
x,y,y2,z: Single;
i0,i1,i2,i,o: Integer;
begin
SetLength(Vx, Sides*Length(Verts)); // array to hold all phase points
// calclate points
for i:=0 to High(Verts) do begin
if i<High(Verts) then o:=1 else o:=-1;
cv:=Verts[i]; // current position
nv:=Verts[i+o]; // next position
d:=VectorNormalize(VectorSubtract(nv,cv)); // direction vector (normalized)
if o<0 then NegateVector(d); // stops flipping because of reversal. comment out to see
u:=VectorNormalize(VectorCrossProduct(d,XHmgVector )); // up vector (assuming Y is up)
r:=VectorNormalize(VectorCrossProduct(d,u)); // right vector

for o:=0 to Sides-1 do begin
{ divide points equally around phase }
x:=Rad*Sin(DegToRad(o*(360/Sides)))*r[0];
y:=Rad*Cos(DegToRad(o*(360/Sides)))*u[1];
y2:=Rad*Cos(DegToRad(o*(360/Sides)))*u[2];
z:=Rad*Sin(DegToRad(o*(360/Sides)))*r[2];
Vx[(i*Sides)+o]:=VectorMake(cv[0]+x, cv[1]+y, cv[2]+z+y2);
end;
end;

{ draw points }
for i:=0 to High(Verts)-1 do begin
if Assigned(Mat) then mat.Material.Apply(rci);
glBegin(GL_TRIANGLE_STRIP)
for o:=0 to Sides do begin
i0:=((i+1)*Sides)+o mod Sides;
i1:=(i*Sides)+o mod Sides;
i2:=((i+1)*Sides)+((o+1) mod Sides);

{ calculate face normal }
fn:=VectorCrossProduct(VectorSubtract(Vx[i0],Vx[i1]),VectorSubtract(Vx[i0],Vx[i2]));
fn:=VectorNormalize(fn);
glNormal3fv(@fn);

{ un-comment to wrap texture around phase }
glTexCoord2f(0,o/Sides); glVertex3fv(@Vx[i0]);
glTexCoord2f(1,o/Sides); glVertex3fv(@Vx[i1]);

{ un-comment to map texture to each side }
// glTexCoord2f(0,o and 1); glVertex3fv(@Vx[i0]);
// glTexCoord2f(1,o and 1); glVertex3fv(@Vx[i1]);
end;
glEnd;
if Assigned(Mat) then Mat.Material.UnApply(rci);
end;

{ clean up }
SetLength(Vx, 0);
end;


also on onRender event for TGLDirectOpenGL component:

procedure TForm1.GLDirectOpenGL1Render(Sender: TObject; var rci: TRenderContextInfo);
var
m: TGLLibMaterial;
v: array of TVector;
begin
{ un-comment to disable lighting and culling }
// gldisable(GL_CULL_FACE);
// glDisable(GL_LIGHTING);

{ replace 'test' with the name of your material }
m:=GLMaterialLibrary1.Materials.GetLibMaterialByNa me('test');

{ you can make adjustments to material 'm' before calling the routine
(eg emission/blending/etc)
}
Phase(8, 0.25, m, v, rci); // draw the phase (Sides,Radius,Material,Pos'n array,ContextInfo)

{ clean up needed?}
m:=nil;
SetLength(v,0);

{ un-comment to re-enable lighting and culling (if disabled above) }
// glEnable(GL_LIGHTING);
// glEnable(GL_CULL_FACE);
end;


I figured as you're already using tglpipes, this method isn't too different except instead of being objects, it's drawn to the buffer. You can adjust the number of sides, radius and segments in the phase so it's fairly flexible. Although it's not setup for splines (from your screenshots they all seemed to be straight lines) it won't take too much modding to incorporate them. it's definitely not perfect, but it kinda works ;)

small app wrapped around the function
Video (http:///izeinfinity.comoj.com/flash/test.html)
Download app (http://izeinfinity.comoj.com/apps/phase.zip)

Any problems, let me know.

JernejL
23-03-2009, 12:59 PM
ize: you made a very nice demo, but that wasn't the problem, the problem is that ideally i would only have half of pipe, which always faces the camera and uv mapping along the length of the pipe / cylinder like this screenshot:

http://mathpudding.com/temp/phasr1.jpg

Your code is good and it could be likely easily changed for the uv mapping method (if we use normal face culling for this then maybe the uv mapping could be just projected somehow and rear faces culled off?)

I will produce a video from old game to show what exactly i meant, the UV mapped side follows the camera source, so that the phasers look as if they are volumetric, the uv mapping also animates along phaser path towards the target.

The phasers have a smaller taper / radius at the origin, on the screenshots i set that to actual diameter of the rest of phaser so that the inner structure was more obviously seen.

I will get a video by the end of the day to show exactly how it works.

JernejL
23-03-2009, 09:24 PM
OK, as promised.. the video of desired effect (from a old game that i am remaking):

http://mathpudding.com/temp/phasers.wmv

The emitter taper size is now less exaggarated so that you can see it's not a straight cylindrical shape, you can see very well in video how the texture on cylinder always faces the camera.

If anyone can help me obtain such effect.. i have my paypal account on hot standby :)

NECRODOME:

I didn't do that.. that's the old game, i am remaking THAT engine and need to achieve that effect in my new game, and i don't have access to old source code

This is the game i am recreating in delphi, i got most of stuff worked out such as loading existing ship models (i wrote a .nif model format parser and renderer for glscene):

EDIT: i added reply to my old post, for some reason i get a database error trying to reply to this topic!!!



Database Error
Please try again. If you come back to this error screen, report the error to an administrator.

edit #2: apparently i get that error everywhere on the forum now.. this is bad!

NecroDOME
23-03-2009, 09:31 PM
Looks nice :)
Like it how you did it with inner and outer beam
EDIT:

oh... ok... :) sorry, didn't read :P.... just looks nice :)


btw:

I also have database errors!!! cannot post new topics :S

(sorry so ruin your topic)

ize
24-03-2009, 11:58 AM
That game looks like fun 8) Hey, thanks for the earlier compliments. Sorry it didn't solve the problem but i think that i can tweak the code to look more like you want. It's almost there from what i can see - the beam does just look like two 8-sided cylinders with normal face culling (like you said). The impact point is definitely just a billboard sprite facing the camera and that's real easy to achieve - you could either:

use a TGLSprite which is purely 2D and won't go too well with the 3D space atmosphere
use a TGLQuad with the following IIRC:



GLQuad1.Pointto(GLCamera1.absolutePosition, YHMGVector); // assuming YAxis is up


It's either PointTo or PointToObject (i'll double check when i'm playing in delphi again)

[thinking out loud]
As for the tapering, that's not a problem at all. If i make the phase a class, then each "node" can also have a radius as well as position (like TGLPipe).

Also, it's not a big leap from there to get some pulsating animation. The phase is a direct line so interpolating several nodes along the path is do-able, then just sine wave the radii of all nodes over time. But i'm getting WAY ahead of myself :) back to the orignal problem ... the glow seems to be using additive textures (which i can't help with as my artist skills are beyond laughable ;D) i'll try the image you posted above.
[/thinking out loud]

Now that i have an idea of the desired result, i'll (try and) post something soon :)

JernejL
24-03-2009, 12:09 PM
ize: the problem isn't the billboard sprite or the taper point or the cylinder geometry, the problem is texture uv mapping, please watch the video carefully and observe how the texture uv mapping on phaser always faces the camera, that is the actual problem i am having.

JernejL
25-03-2009, 05:54 PM
So, suddently everyone is fresh out of ideas? :(

ize
25-03-2009, 08:26 PM
Hi there. Well don't i feel like the prize idiot - i ran off at 1000 mph ... in completely the wrong direction :-[ I came online last night to upload the 2nd version and saw your post that it wasn't right. So went back to the drawing board and studied the video for about 10mins frame by frame to see exactly what it did.

After much head scratching/headaches/nosebleeds ;) i think i have what you're looking for!

Sorry, no source at the mo because it's in such a mess after being ripped to shreds! All the materials are embedded in the app, but they can easily be loaded at runtime, etc. There's also no need to have the variations like i've done - you can have one "template" material, assign it to the phase and then make changes to the phase material leaving the original untouched.
The only thing i couldn't get right was the highlighting of the phaser. I think the best "cheat" would just be to put it in the texture. I'm no artist so i didn't try it.

I can give you an outline of how i achived it though. It's probably wrong as i'm not a maths genius. It involved a LOT of trial and even more errors :)


I calculated the direction from the camera to the first node in the phase and did a cross product of that with the phaser direction to give me the final vector (eye vector).
After that i calculated the angle of the phase direction and eye vector using the phase up vector as a reference. This angle returns -1 .. 1 which i changed to 0 .. 2 and made it signed so i know which side it was on -=left +=right
Finally i used this number to modify the uv tex coords to "slide" the texture around the phaser


Here ya go:
Video (http://izeinfinity.comoj.com/flash/test2.html)
Download app (http://izeinfinity.comoj.com/apps/phase2.zip)

Let me know if this is at least in the right direction ???

laters

User137
25-03-2009, 08:33 PM
Well.. to problem of texturemapping a cylinder to point camera, we have few things known:
1. U-coordinate of each vertex never change, so we only need to count 1 value; V-coordinate.
BUT
2. If we think about how texture behaves if model stands still and only texture-coordinates change, we know that the animation and the general looks would be different depending on angle. Sort of distortion/ripples happen. So we can skip step 1 and rotate the cylinder along its center, so we still have only 1 value to calculate and that is rotation angle.
3. What values we have to use? We can use glGet on GL_MODELVIEW_MATRIX to get all 3 rotation vectors that camera uses. And we can count normal vector to cylinder when it is at 0 degree rotation (which is completely free to choose along the surface of cylinder).
4. That all known, we should better draw some picture to get a good overview on what vectors we are comparing, or analyze them realtime in program... and that goes way beyond a simple forum post xx(

JernejL
25-03-2009, 09:21 PM
Hi there. Well don't i feel like the prize idiot - i ran off at 1000 mph ... in completely the wrong direction :-[ I came online last night to upload the 2nd version and saw your post that it wasn't right. So went back to the drawing board and studied the video for about 10mins frame by frame to see exactly what it did.

After much head scratching/headaches/nosebleeds ;) i think i have what you're looking for!

Sorry, no source at the mo because it's in such a mess after being ripped to shreds! All the materials are embedded in the app, but they can easily be loaded at runtime, etc. There's also no need to have the variations like i've done - you can have one "template" material, assign it to the phase and then make changes to the phase material leaving the original untouched.
The only thing i couldn't get right was the highlighting of the phaser. I think the best "cheat" would just be to put it in the texture. I'm no artist so i didn't try it.

I can give you an outline of how i achived it though. It's probably wrong as i'm not a maths genius. It involved a LOT of trial and even more errors :)


I calculated the direction from the camera to the first node in the phase and did a cross product of that with the phaser direction to give me the final vector (eye vector).
After that i calculated the angle of the phase direction and eye vector using the phase up vector as a reference. This angle returns -1 .. 1 which i changed to 0 .. 2 and made it signed so i know which side it was on -=left +=right
Finally i used this number to modify the uv tex coords to "slide" the texture around the phaser


Here ya go:
video: http://izeinfinity.comoj.com/flash/test2.html
Download app (http://izeinfinity.comoj.com/apps/phase2.zip)

Let me know if this is at least in the right direction ???

laters


This is awesome, it is perfect! you did a most awesome thing, exactly what i need to finish my phasers :D i can finally move the project forward now with weapons fully charged :D can't wait for the src :) i remember i mentioned paypal on first page, i'll be gladly donating something if you wish :)

The only thing i couldnt figure out is how to load a custom texture in the app.

User137: thanks for helping, i realise that ize came up with a working solution now, but i still appreciate your help, unfortunately i'm not that good with math to understand half of it, i usually go around trial and error with such complex things, in this phasers case.. it didn't quite work.. :(

ize
25-03-2009, 09:42 PM
Glad i could help. As for the payment, thankyou very much for the offer but don't worry about it. It was a really fun thing to try and figure out :)

All the textures are fixed in the app. What i meant was that you could load textures to the Material Library at runtime in your game. I just figured it would be easier that way as i didn't have to worry about changing the properties of materials once loaded.

i'll make a start on cleaning up and fully commenting the src and will post here soon

ize
27-03-2009, 07:18 AM
Hey there.
I wasn't sure how you were going to include it in your game so i have moved all the relevant code, placed it in its own unit and have made it a class. This way you have the option of adding it, or ripping the code out of it.

I also made a couple of mods to it:

Phaser can now have a parent object. if it's assigned, the origin becomes relative to parent, otherwise it's absolute. Eg:
Start(NullVector, GLsphere1.AbsolutePosition) will set the origin to (0,0,0) if no parent is assigned and the object's center if it is. The target is always absolute
Texture can now face any direction(it still rotates around the phaser). Just supply the eye origin to the Update method


If you are going to use the class then just a couple of things to note:

You must have a TGLDirectOpenGL component in your GLscene and never move the position of it from (0,0,0) or this will offset the phaser
Only call the Update method from the TGLDirectOpenGL onRender event (all other methods can be called from anywhere)
Materials must have their Texture wrapping set to tmBoth or the effect won't work (the repeat and especially the facing)
For all methods that expect coordinates, it's best to use an absolute position (except in the case of Start method


All compiled with Delphi 2009 but hopefully it will work in other versions. Zip contains:

testbed app from previous post (src tidied up but not commented)
phaser unit (src commented + <unzipped folder>\help\index.html)


Let me know of any bugs i may have missed ;)
Download Src (http://izeinfinity.comoj.com/apps/phaser_src.zip)

JernejL
27-03-2009, 09:07 PM
This is cool, i will probably make a custom component to hold many phasers, also this gldirect is annoying to use, when glscene always does frustum culling on it and you can't turn it off.. i kinda made my own workaround for this to always move the gldirect into camera view and reverse the matrix so it renders in global space

Also i had to hack the demo a bit.. since it wouldnt compiler properly with D7 until i removed the akward compiler directives, inlines and some other fixes :\

I'll definetly keep you posted to see the final results.

JernejL
29-03-2009, 03:52 PM
http://mathpudding.com/temp/phasersfirsttest.jpg

This is how it looks now, it's pretty good looking, i still need to add colors and proper texture "flowing" animation into the target direction and stretching of the texture but it looks very promising.

You definetly deserved a beer for this one!

ize
30-03-2009, 07:13 PM
Sorry for the delayed reply - have been having internet problems @ home :( That's looking amazing ;D 8) Glad i could help, but sorry for all the hacks/fixes you had to do. i might see if i can get my hands on an earlier version of Delphi so i can test compatability of my apps. I realise what with unicode in D2009 and operator overloading from D2006 onwards the best bet would be to get D7 and then work forwards rather than backwards.

You've probably got it sorted already, but the flowing should be easy if you're using the update method from the class. Pass the deltatime(dt) to the drawphase method and then you can offset the x texture coord over time. pm me if my code is giving you trouble,

Browsing this site and now working on this has definitely given me an appetite to start on my own little project :)

JernejL
31-03-2009, 08:55 PM
There's a slight problem with uv mapping if you can help me fix this:

http://mathpudding.com/temp/phaserproblem.jpg

There's only a part of whole texture shown, this works very bad because it cuts out the phaser speckles in texture, i tries multiplying the V texture mapping by 3, and got a semi-useable fix, but then it the texture shifts wrong when seen from specific angles, could you look into this so the whole texture height is mapped to the exact half of visible surface?

ize
01-04-2009, 12:38 AM
Whoops! Sorry about that. I assumed the texture would wrap the whole phaser not just the visible side - mainly because of the black borders on the texture. Also, it looks like i didn't take the v repeats into account on the offset :-[

Here's a fix:

Replace code in method DrawPhase:

glTexCoord2f((i+1)/(fncount-1)*xrep, (yrep*1.5)-((fyrep*o)/fsides)-fofs*yrep);
glVertex3fv(@fverts[trenderItem(p),a]);
glTexCoord2f(i/(fncount-1)*xrep, (yrep*1.5)-((fyrep*o)/fsides)-fofs*yrep);
glVertex3fv(@fverts[trenderItem(p),b]);


with this:

var
u,v: single; // add to method

// this line tries to keep visible textures centered around offset
if Odd(fyrep) then v:=0.5 else v:=0;

u:=(2*fyrep+v)-((2*fyrep*o)/fsides)-(fofs*2*fyrep);
glTexCoord2f((i+1)/(fncount-1)*xrep, u);
glVertex3fv(@fverts[trenderItem(p),a]);
glTexCoord2f(i/(fncount-1)*xrep, u);
glVertex3fv(@fverts[trenderItem(p),b]);


haven't tested yet, but it looks like it'll work ;) probably best to still leave a border on the textures just to make sure

JernejL
01-04-2009, 06:52 PM
http://mathpudding.com/temp/betterphaser.jpg

Perfect, thanks :D

ize
01-04-2009, 08:42 PM
No problem ;)

aalina
18-10-2011, 07:10 AM
These phasers were a departure from previous designs used by Starfleet with a dual-fire modification, as this type 1 hand unit was not designed to be mated with a type 2power-pack grip. The power output of this weapon was rated at nearly three-times that of previous hand phaser models,