PDA

View Full Version : How to render billboards in "local space"



chronozphere
16-09-2009, 07:52 PM
Hey everyone 8)

I want to use particle-systems in my compo-entry, and I allready have a nice particlesystem module working. However, it would be great if I could define a local coordinate system for each particle-system. I could for example, emit fire particles that move parrallel to the local Z-axis. Using a matrix, I could "orient" this beam of particles anywhere in my world. :)

The problem that arises is: "How to deal with the billboards".

For billboards, My code is as follows:


var
X, Y, Z: TVector;
m: TMatrix;
begin
//Compute billboard matrix, where positive Z points away from the camera
//CamVec := Camera.LookAt - Camera.Pos
//Pos = position of particle

Z := VecNorm( CamVec );
X := VecNorm(VecCross(VecMake(0, 1, 0), Z));
Y := VecNorm(VecCross(X, Z));

Result := matIdentity();
Result[0, 0] := X.x;
Result[0, 1] := X.y;
Result[0, 2] := X.z;
Result[1, 0] := Y.x;
Result[1, 1] := Y.y;
Result[1, 2] := Y.z;
Result[2, 0] := Z.x;
Result[2, 1] := Z.y;
Result[2, 2] := Z.z;
Result[3, 0] := pos.x;
Result[3, 1] := pos.y;
Result[3, 2] := pos.z;

//Rotate about Z-axis to allow particle rotation (each particle can have a different angle
//This is the reason I didn't use PointSprites. They dont allow this kind of rotation
m := matRotateZ(DegToRad(Angle));
Result := matMul(m, Result);
end;


This code builds a matrix that places the billboard in the world. The billboard would be on the local XY plane.

If i start adding transformations to the ModelView matrix, this code doesn't work anymore.
That's because the camera is defined in world space, and therefore my particles need to be defined in worldspace aswell, in order for the code to work.
If I had a seperate model matrix, I could let it transform my particles to world-space, and then use this code. But the Model and view matrices are combined into "ModelView" and it's not easy to seperate them. I need another sollution. ???

Does anyone know how to make this code "transformation-proof"?

Thanks in advance. :)

chronozphere
17-09-2009, 09:28 AM
Never mind. This is my sollution:



> Make backup of modelview matrix
> Transform all particle positions with a given matrix M to world-space
> Make sure that the modelview matrix only contains the view transformation
> Use the code above to "orient" each billboard.
> Render billboards
> Restore old modelview matrix

User137
17-09-2009, 03:17 PM
The obvious solution would be to first calculate M for invert rotation of modelview matrix, then for each sprite do:

glPushMatrix
glTranslatef
glMultMatrix(M)
Render
glPopMatrix

I would imagine it to be equally fast.

Andreaz
18-09-2009, 07:39 AM
You basically wants to rotate the particles around the forward vector of the modelview matrix:



function Matrix_GetForward(const Matrix: TMatrix4f): TVector3f;
begin
Result.X:= Matrix[02];
Result.Y:= Matrix[06];
Result.Z:= Matrix[10];
end;

...

Vector:= Matrix_GetForward(BillBoardMatrix);

MatRotate:= Matrix_Rotation(Particle.Spin, Vector);


I haven't tested this code in practice, but i think it should do the trick.

chronozphere
21-09-2009, 08:21 AM
Hey.. Thanks for the advice. Those are very handy tricks. :)
I'll test them soon.