PDA

View Full Version : Volumetric Clouds



M109uk
13-11-2007, 09:51 PM
Hi all,

I found a C++ OpenGL example of Volumetric Clouds a while back, and found it on my HDD while cleaning up.. so i am trying to make a GLScene port of it... now my C++ skills are urm some what limited, but i have managed to convert it (at least to the best of my knowledge).

It seems to compile ok without errors or warnings, but i can't seem to get it to work very well.

There are 2 main routines that need to be called, update and render (of course), if i just have update then the program runs, however if i have update and render then the program crashes on every 8 or 12 loop cycle with an 'Access Violation', now i suspect that it has something to do with the call to glDrawArrays(GL_QUADS, 0, Length(Cloud.vBuffer));, this routine is in both the RenderCloud3D procedure (called when rendering) and MakeCloudImpostor procedure (called when upating).

Its either because my conversion is rubbish, or i need to put some form of delay between updating and rendering, or some other means.
Any suggestions?

Heres the code to browse: Here (http://www.pulse-soft.oneuk.com/index.php?option=com_docman&task=doc_download&gid=5&Itemid=57)

Many thanks
Nic

p.s. sorry the code is some what a mess....

EDIT:
I decided to double check the cloud data being read, would having the single values out of range cause access violations?

if so, is there a problem between the method i load the data file compared to the method from c++?

User137
13-11-2007, 11:16 PM
I wonder if problem is here:
glVertexPointer(3, GL_FLOAT, 0, @Cloud.vBuffer);
glColorPointer(4, GL_FLOAT, 0, @Cloud.cBuffer);
glTexCoordPointer(2, GL_FLOAT, 0, @Cloud.tBuffer);

I don't have GLScene installed to test but try using

glVertexPointer(3, GL_FLOAT, 0, @Cloud.vBuffer[0]);
glColorPointer(4, GL_FLOAT, 0, @Cloud.cBuffer[0]);
glTexCoordPointer(2, GL_FLOAT, 0, @Cloud.tBuffer[0]);

Setlength made dynamic arrays don't work same way as normal or allocated ones if i remember, instead it's like a pointer to memory space that contains the cells in an array.

M109uk
13-11-2007, 11:26 PM
Wow, sharp eye... that seemed to have solved the access violation errors :)

Now the only problem is that the speed is, urm well none existant..

Many thanks

M109uk
14-11-2007, 06:46 PM
Hi,

Im still trying to find out why my version is a lot slower than the C++ version, although i have a few ideas of my own to speed it up. but for now i wish to confirm that my C++ conversion is urm correct.. the main parts i am unsure about are the following:

from:


inline float __fastcall carmack_func(float x)
{
int carmack;
float isx, halfx; //Inverse Squareroot of x

halfx = 0.5f*x;
carmack = *(int*)&x;
carmack = 0x5f3759df - (carmack>>1);
isx = *(float*)&carmack;

isx = isx*(1.5f-halfx*isx*isx); //Newton-Rhapson step, add more for accuracy

return isx;
}

to:

function carmack_func(x: Single): Single;
var
carmack: Integer;
isx,halfx: Single;
begin
halfx := 0.5*x;
carmack := Round(x);
If carmack > 1 Then
carmack := $5f3759df-(carmack) Else
carmack := $5f3759df-(1);
isx := carmack;
isx := isx*(1.5-halfx*isx*isx);
Result := isx;
end;


the above im sure is wrong, because i really did'nt have a clue about parts of the code and could'nt find any resources.

from:


*(vp++) = Puff->Position + Corner1 * Puff->Size;
*(tp++) = v1;
*(cp++) = ParticleColor;

to:

Cloud.vBuffer[j] := Vector3fMake(Cloud.Puffs[i].Position[0]+Corner1[0]*Cloud.Puffs[i].Size,
Cloud.Puffs[i].Position[1]+Corner1[1]*Cloud.Puffs[i].Size,
Cloud.Puffs[i].Position[2]+Corner1[2]*Cloud.Puffs[i].Size);
Cloud.tBuffer[j] := v1;
Cloud.cBuffer[j] := ParticleColor;
Inc(j);


now im fairly confident in assuming this is going through the array's setting the values?!

and another question, is having the records/classes as a pointer quicker?

e.g.

vBuffer: Array Of TVector3f;
..
for j := 0 to 2500 do vBuffer[i] := Vector3fMake(0,0,0);

Many thanks
Nic

Robert Kosek
14-11-2007, 07:19 PM
I know it might not work, or yield similar results (I'm not good with C), but this should do what you're after. I tried reducing the legwork that was going on as much as possible to speed things up though. Try this:
function carmack_func(const x: double): double; inline;
var halfx: double;
carmack: integer;
begin
halfx := x * 0.5; // Floating point multiplication is usually faster.
carmack := $5f3759df - (int(x) shr 1);
result := carmack * (1.5 - halfx * carmack * carmack);
end;To speed that up further, try changing it to a procedure and pass the floating point result as an OUT parameter. That could speed things a little.

I don't know about the second part. It's been years since I touched OpenGL by hand, and even then I wasn't particularly good at it. However, you might be faster at it if you pass things as a record ... I just don't know. You could try using a pointer for increased speed, but I don't know if there would be a gain there. Try this to see:

procedure pointerWalk;
var
vBuffer: PVector3f;
count: integer;
begin
count := 2500;
// Assign the memory block to the pointer, I don't remember the Delphi
// code off-hand. But the size is 'SizeOf(TVector3f)*2500' if you need
// to know how. :P
repeat
vBuffer^ := Vector3fMake(0,0,0);
Inc(vBuffer);
Dec(Count);
until count = 0;
end;I honestly don't know that it'd make much of a difference, if any.

Oh, and all this was written in ConText/Firefox, so no promises that it actually functions as-is. You might need to tweak it a little.

EDIT:

On second thought, if you're only making a blank array of vectors it'd be faster to do:
FillChar(vBuffer, #0, SizeOf(vBuffer));That's as utterly fast as you can do it without assembler. ;)

M109uk
14-11-2007, 08:14 PM
Great thanks for the quick reply :D

I have inserted your carmack_func, there where 2 problems, delphi didn't like the inline; nor the int(X), but removing the inline; and changing int(x) to Round(x) seems to compile :)

I shall try using the pointers now, i noticed that pointers where being used in the C++ version, but since im not too good with pointers i tried it using records instead.

I shall post back with the results :)

Thanks again
Nic

M109uk
14-11-2007, 08:38 PM
Hi again,

I have changed the code to use pointers instead, however i am getting an access violation error when i add data to the pointer (around the 20th item to be added)

am i doing something wrong...

heres the code im using:

//---- load cloud data
GetMem(Cloud.vBuffer, (SizeOf(TVector3f)*(Length(Cloud.Puffs)*4)));
GetMem(Cloud.tBuffer, (SizeOf(TVector3f)*(Length(Cloud.Puffs)*4)));
GetMem(Cloud.cBuffer, (SizeOf(TVector3f)*(Length(Cloud.Puffs)*4)));

//---- add data to pointers
procedure AddToMem(Cloud: TVolumetricCloud; v2: TVector2f; v3: TVector3f; v4a,v4b: TVector4f);
begin
Cloud.vBuffer^ := v3;
Inc(Cloud.vBuffer); <-------------- ERROR HERE
Cloud.cBuffer^ := v4a;
Inc(Cloud.cBuffer);
Cloud.IcBuffer^ := v4b;
Inc(Cloud.IcBuffer);
Cloud.tBuffer^ := v2;
Inc(Cloud.tBuffer);
end;

//

For i := 0 To High(Cloud.Puffs) Do
Begin

iv3 := Vector3fMake(Cloud.Puffs[i].Position[0]+Corner1[0]*Cloud.Puffs[i].Size,
Cloud.Puffs[i].Position[1]+Corner1[1]*Cloud.Puffs[i].Size,
Cloud.Puffs[i].Position[2]+Corner1[2]*Cloud.Puffs[i].Size);
AddToMem(Cloud, v1, iv3, pColor, pColor2);
iv3 := Vector3fMake(Cloud.Puffs[i].Position[0]+Corner2[0]*Cloud.Puffs[i].Size,
Cloud.Puffs[i].Position[1]+Corner2[1]*Cloud.Puffs[i].Size,
Cloud.Puffs[i].Position[2]+Corner2[2]*Cloud.Puffs[i].Size);
AddToMem(Cloud, v2, iv3, pColor, pColor2);
iv3 := Vector3fMake(Cloud.Puffs[i].Position[0]+Corner3[0]*Cloud.Puffs[i].Size,
Cloud.Puffs[i].Position[1]+Corner3[1]*Cloud.Puffs[i].Size,
Cloud.Puffs[i].Position[2]+Corner3[2]*Cloud.Puffs[i].Size);
AddToMem(Cloud, v3, iv3, pColor, pColor2);
iv3 := Vector3fMake(Cloud.Puffs[i].Position[0]+Corner4[0]*Cloud.Puffs[i].Size,
Cloud.Puffs[i].Position[1]+Corner4[1]*Cloud.Puffs[i].Size,
Cloud.Puffs[i].Position[2]+Corner4[2]*Cloud.Puffs[i].Size);
AddToMem(Cloud, v4, iv3, pColor, pColor2);
End;


im sure i've missed something really dumb..

Thanks
Nic

Robert Kosek
14-11-2007, 08:42 PM
What are the types of the Cloud properties: vBuffer, tBuffer, cBuffer? I'm not a pointer expert, but I think I made a mistake and gave the wrong type; etc. A potential problem is that you're manipulating what should be the list "head" rather than the current item on the tail. Hard to say without knowing the actual types in this case.

M109uk
14-11-2007, 08:47 PM
Ah sorry, i forgot to post that bit :oops:

type
PVector2f = ^TVector2f;
PVector3f = ^TVector3f;
PVector4f = ^TVector4f;

TVolumetricCloud = Class
//
vBuffer: PVector3f;
tBuffer: PVector2f;
cBuffer: PVector4f;
IcBuffer: PVector4f;
end;

Thanks

Traveler
14-11-2007, 08:50 PM
Mind you, Int() is not the equivalent of round(). I think you'd be better off with trunc().

see

ShowMessage('Round(12.75) = '+IntToStr(Round(12.75)));
ShowMessage('Trunc(12.75) = '+IntToStr(Trunc(12.75)));
ShowMessage(' Int(12.75) = '+FloatToStr(Int(12.75)));
or this site (http://www.delphibasics.co.uk/RTL.asp?Name=Int).

M109uk
14-11-2007, 09:15 PM
Thanks for that, i always woundered what the difference between the two was :)

Robert Kosek
14-11-2007, 09:19 PM
Ah sorry, i forgot to post that bit :oops:

type
PVector2f = ^TVector2f;
PVector3f = ^TVector3f;
PVector4f = ^TVector4f;

TVolumetricCloud = Class
//
vBuffer: PVector3f;
tBuffer: PVector2f;
cBuffer: PVector4f;
IcBuffer: PVector4f;
end;

ThanksOkay, this is the problem and is my fault. What you need is this type for the buffers:

type
TVector3fArray = array of Vector3f;
PVector3fArray = ^TVector3fArray;
//...

TVolumetricCloud = Class
vBuffer&#58; PVector3fArray;
//...
end;

//..

//OnCreate...
var cur&#58; PVector3f;
counter&#58; Integer;
begin
GetMem&#40;vBuffer, SizeOf&#40;TVector3f&#41; * Length&#40;Puffs&#41;&#41;;
cur &#58;= Pointer&#40;vBuffer^&#91;0&#93;&#41;;
counter &#58;= Length&#40;Puffs&#41;;
while counter > 0 do begin
// Manipulation here...
Inc&#40;Cur&#41;;
Dec&#40;Counter&#41;;
end;
end;

You should understand how to expand upon this by now, but I'll give you the basics. Sometimes pointers really aren't worth it--especially for arrays. Now, you could do a single/double linked list, but there would be no increase in speed to set the vertex buffer that way (the API's are C and want arrays...).

User137
14-11-2007, 09:22 PM
I have changed the code to use pointers instead, however i am getting an access violation error when i add data to the pointer (around the 20th item to be added)

am i doing something wrong...

heres the code im using:
//---- add data to pointers
procedure AddToMem(Cloud: TVolumetricCloud; v2: TVector2f; v3: TVector3f; v4a,v4b: TVector4f);
begin
Cloud.vBuffer^ := v3;
Inc(Cloud.vBuffer); <-------------- ERROR HERE
Cloud.cBuffer^ := v4a;
Inc(Cloud.cBuffer);
Cloud.IcBuffer^ := v4b;
Inc(Cloud.IcBuffer);
Cloud.tBuffer^ := v2;
Inc(Cloud.tBuffer);
end;
im sure i've missed something really dumb..

Propably :) That code is trying to increase pointers by 1 like you showed in class definition. Try
Inc(Cloud.vBuffer^);
etc...

M109uk
14-11-2007, 09:57 PM
User137:
Thanks for the idea,
i gave it a try, and it just kept coming back with an invalid typcast error.

Robert Kosek:
Thanks again,
I had to make a small adjustment (otherwise i kept getting access violations again)

TVector3fArray = Array [0..0] Of TVector3f;
PVector3fArray = ^TVector3fArray;

I hav'nt properly tested it to see if the values are going in ok, since now i have another problem i completly forgot about, haha.

I have another procedure that sorts the records depending on the puffs distance from the camera, now i know my sort routine is uterly trash, and probably contributes to the most of the lack of speed, however here it is:


procedure TGLVolumetricClouds.SortParticles(Cloud: TVolumetricCloud; mode: Integer);

procedure swap(iFrom,iTo: Integer);
var
tmpPuff: TCloudPuff;
begin
tmpPuff := Cloud.Puffs[iFrom];
Cloud.Puffs[iFrom] := Cloud.Puffs[iTo];
Cloud.Puffs[iTo] := tmpPuff;
end;

procedure sort(Toward: Boolean);
var
i,j: Integer;
tmpPuff: TCloudPuff;
begin
For i := 0 To High(Cloud.Puffs) Do
For j := 0 To High(Cloud.Puffs) Do
Begin
If ((Toward) And (Cloud.Puffs[i].DistanceToCam > Cloud.Puffs[j].DistanceToCam)) Or
((Not Toward) And (Cloud.Puffs[i].DistanceToCam < Cloud.Puffs[j].DistanceToCam)) Then
swap(i, j);
End;
end;

var
done,do_swap,useSTL: Boolean;
i,j: Integer;
begin
done := False;
useSTL := True;

If useSTL Then
Begin
Case mode Of
SORT_AWAY: sort(False);
SORT_TOWARD: sort(True);
End;
End Else
Begin
while (Not done) Do
Begin
done := True;
For i := 0 To High(Cloud.Puffs) Do
For j := i+1 To High(Cloud.Puffs) Do
Begin
do_swap := false;
Case mode Of
SORT_AWAY: do_swap := (Cloud.Puffs[i].DistanceToCam <Cloud> Cloud.Puffs[j].DistanceToCam);
End;

If do_swap Then
Begin
swap(i, j);
done := False;
End;
End;
End;
End;
end;


Im guessing this would'nt effect the pointers, but i have an assign procedure for the cloud, which needs to copy the pointer, now im assuming if i just did Cloud.vBuffer := Source.vBuffer; that if i make changes this will effect both clouds. would it be best to clear and recreate the pointer (cloud.vBuffer) and then copy the memory (somehow)?

Many Thanks
Nic

Robert Kosek
14-11-2007, 10:12 PM
Well, the sorting is beyond me, but not the swappage of pointers. That's really simple once you figure it out. Here's the gist:
procedure SwapPointers&#40;var p1,p2&#58; Pointer&#41;;
var
tmp&#58; pointer;
begin
tmp &#58;= p1;
p1 &#58;= p2;
p2 &#58;= tmp;
end;It really is that simple. :D If it complains about the pointer type or anything, just typecast it into a pointer when you pass it.

M109uk
14-11-2007, 10:29 PM
Great thanks :)

seems to work, now i seem to be having problems again with the following section, it loops through a few times and then an access violation:


glVertexPointer(3, GL_FLOAT, 0, Cloud.vBuffer);
glColorPointer(4, GL_FLOAT, 0, Cloud.cBuffer);
glTexCoordPointer(2, GL_FLOAT, 0, Cloud.tBuffer);

glDrawArrays(GL_QUADS, 0, Length(Cloud.Puffs)*4);


i assumed to change from '@Cloud.vBuffer[0]' to 'Cloud.vBuffer'?

Thanks again
Nic

Robert Kosek
14-11-2007, 10:36 PM
Try this instead, as far as I can remember this is the correct form. Though, why do you keep multiplying the size by 4? That is beyond me a little, since I'm trying to figure out why you need 4 times the size of the one array.


glVertexPointer&#40;3, GL_FLOAT, 0, Pointer&#40;Cloud.vBuffer^&#91;0&#93;&#41;&#41;;
glColorPointer&#40;4, GL_FLOAT, 0, Pointer&#40;Cloud.cBuffer^&#91;0&#93;&#41;&#41;;
glTexCoordPointer&#40;2, GL_FLOAT, 0, Pointer&#40;Cloud.tBuffer^&#91;0&#93;&#41;&#41;; This just gets the pointer to the first item like before, rather than the array. C prefers it this way AFAIK.

M109uk
14-11-2007, 10:44 PM
I tryed that and got an invalid typcast error, would this work:


glVertexPointer(3, GL_FLOAT, 0, @Cloud.vBuffer^[0]);
glColorPointer(4, GL_FLOAT, 0, @Cloud.cBuffer^[0]);
glTexCoordPointer(2, GL_FLOAT, 0, @Cloud.tBuffer^[0]);


Im multiplying them by 4 because each puff is actually Quad :) so i pass 4 vertices for each puff.

Robert Kosek
14-11-2007, 11:27 PM
Ah, okay. So what is the function expecting, typewise? Maybe try removing the array index portion and just throw it the buffer with a @ prefix to the whole thing. IE: @Cloud.vBuffer);

User137
15-11-2007, 10:58 AM
I have changed the code to use pointers instead, however i am getting an access violation error when i add data to the pointer (around the 20th item to be added)

am i doing something wrong...

heres the code im using:
//---- add data to pointers
procedure AddToMem(Cloud: TVolumetricCloud; v2: TVector2f; v3: TVector3f; v4a,v4b: TVector4f);
begin
Cloud.vBuffer^ := v3;
Inc(Cloud.vBuffer); <-------------- ERROR HERE
Cloud.cBuffer^ := v4a;
Inc(Cloud.cBuffer);
Cloud.IcBuffer^ := v4b;
Inc(Cloud.IcBuffer);
Cloud.tBuffer^ := v2;
Inc(Cloud.tBuffer);
end;
im sure i've missed something really dumb..

Propably :) That code is trying to increase pointers by 1 like you showed in class definition. Try
Inc(Cloud.vBuffer^);
etc...

*sigh* I wasn't really thinking clearly when i wrote that :lol: procedure AddToMem says something about what you want to do in it... Original procedure propably did something only C can do, now in pascal you likely need a new approach completely. So.. i think plan is to add 1 vertex to array and same time make preparations so next call will also add 1 after it. Need to make sure the array is resized and update some Count variable, then assign parameter info to vBuffer[Count-1] that is last index.

And about sorting, this is 1 efficient structure:
for i:=0 to Count-2 do
for j:=i+1 to Count-1 do
// Compare here and swap if needed

// Notice how it ignores all useless calls, like this way would make final compare to item itself, not to mention amount of extra calls it there wasn't i+1
for i:=0 to Count-1 do
for j:=i+1 to Count-1 do
But still there exist faster ways, i'm not very much familiarized with them and they are propably made for certain kinds of arrays.

Edit: Ok i take my words back a bit, it is all propably possible in pascal too, but this line
Inc(Cloud.vBuffer);
was actually made to increase the pointer (the place that array starts, note you would need to revert it backwards too if want to use it), and likely not by 1, but 12 that is sizeof(TVector3f). Maybe something like (i'm not sure):
pointer(Cloud.vBuffer):=pointer(integer(Cloud.vBuf fer)+12);

M109uk
15-11-2007, 01:40 PM
Robert Kosek:
The procedure expects a pointer type.
I shall try your suggestion. Thanks.

User137:
Well im not really any good with c/c++ and my only experiance with it was a simple hellow world application about 5years ago, but here is the C++ version:



*&#40;vp++&#41; = Puff->Position + Corner1 * Puff->Size;
*&#40;tp++&#41; = v1;
*&#40;cp++&#41; = ParticleColor;

*&#40;vp++&#41; = Puff->Position + Corner2 * Puff->Size;
*&#40;tp++&#41; = v2;
*&#40;cp++&#41; = ParticleColor;

*&#40;vp++&#41; = Puff->Position + Corner3 * Puff->Size;
*&#40;tp++&#41; = v3;
*&#40;cp++&#41; = ParticleColor;

*&#40;vp++&#41; = Puff->Position + Corner4 * Puff->Size;
*&#40;tp++&#41; = v4;
*&#40;cp++&#41; = ParticleColor;


When the cloud is created, it goes to the manager and randomly chooses a cloud data file (this data file contains information on each puff), it then resizes the vBuffer, etc to the required size to fit with the amount of puffs:


GetMem(vBuffer, SizeOf(TVector3f)*(Length(Puffs)*4));


Now on every update and render the vBuffer, etc seems to get updated to fit with the position of the camera and sun.

How ever in an attempt to speed things up, i have moved the code to only work in the update, so now it looks like:

procedure AddToMem(Cloud: TVolumetricCloud; Index: Integer; v2: TVector2f; v3: TVector3f; v4a,v4b: TVector4f);
begin
Cloud.vBuffer^[Index] := v3;
// Inc(Cloud.vBuffer^);
Cloud.cBuffer^[Index] := v4a;
// Inc(Cloud.cBuffer^);
Cloud.IcBuffer^[Index] := v4b;
// Inc(Cloud.IcBuffer^);
Cloud.tBuffer^[Index] := v2;
// Inc(Cloud.tBuffer^);
end;

procedure TGLVolumetricClouds.buildArrays(Cloud: TVolumetricCloud; Camera,Sun: TVector3f; Alpha: Single);
var
i,j: Integer;
omega2,costheta,phase: Single;
v1,v2,v3,v4: TVector2f;
iv3,vx,vy,Light,vv3,Omega,Corner1,Corner2,Corner3, Corner4: TVector3f;
pColor,pColor2: TVector4f;
mat: Array [0..15] Of Single;
begin
vv3 := Vector3fMake(Camera[0]-Sun[0], Camera[1]-Sun[1], Camera[2]-Sun[2]);
Light := VectorNormalize(vv3);

glGetFloatv(GL_MODELVIEW_MATRIX, @mat);

vx := Vector3fMake(mat[0], mat[4], mat[8]);
vy := Vector3fMake(mat[1], mat[5], mat[9]);

v1 := Vector2fMake(1, 0);
v2 := Vector2fMake(0, 0);
v3 := Vector2fMake(0, 1);
v4 := Vector2fMake(1, 1);

Corner1 := Vector3fMake(-vx[0]-vy[0], -vx[1]-vy[1], -vx[2]-vy[2]);
Corner2 := Vector3fMake( vx[0]-vy[0], vx[1]-vy[1], vx[2]-vy[2]);
Corner3 := Vector3fMake( vx[0]+vy[0], vx[1]+vy[1], vx[2]+vy[2]);
Corner4 := Vector3fMake( vy[0]-vx[0], vy[1]-vx[1], vy[2]-vx[2]);

j := 0;
For i := 0 To High(Cloud.Puffs) Do
Begin
Omega := Vector3fMake(Cloud.Puffs[i].Position[0]-Camera[0],
Cloud.Puffs[i].Position[1]-Camera[1],
Cloud.Puffs[i].Position[2]-Camera[2]);

omega2 := Omega[0]*Omega[0]+Omega[1]*Omega[1]+Omega[2]*Omega[2];
omega2 := carmack_func(omega2);

//omega2 is now 1 / Mag(Omega)
Omega[0] := Omega[0]*omega2;
Omega[1] := Omega[1]*omega2;
Omega[2] := Omega[2]*omega2;

costheta := VectorDotProduct(Omega, Light);
phase := 0.75*(1.0+costheta*costheta);

// 3D
pColor[0] := (0.3+Cloud.Puffs[i].Color[0]*phase)*Alpha;
pColor[1] := (0.3+Cloud.Puffs[i].Color[1]*phase)*Alpha;
pColor[2] := (0.3+Cloud.Puffs[i].Color[2]*phase)*Alpha;
pColor[3] := Cloud.Puffs[i].Color[3]*Cloud.Puffs[i].Life*Alpha;

// Imposter
pColor2[0] := 0.3+Cloud.Puffs[i].Color[0]*phase;
pColor2[1] := 0.3+Cloud.Puffs[i].Color[1]*phase;
pColor2[2] := 0.3+Cloud.Puffs[i].Color[2]*phase;
pColor2[3] := Cloud.Puffs[i].Color[3]*Cloud.Puffs[i].Life;

iv3 := Vector3fMake(Cloud.Puffs[i].Position[0]+Corner1[0]*Cloud.Puffs[i].Size,
Cloud.Puffs[i].Position[1]+Corner1[1]*Cloud.Puffs[i].Size,
Cloud.Puffs[i].Position[2]+Corner1[2]*Cloud.Puffs[i].Size);
AddToMem(Cloud, j, v1, iv3, pColor, pColor2);
Inc(j);
iv3 := Vector3fMake(Cloud.Puffs[i].Position[0]+Corner2[0]*Cloud.Puffs[i].Size,
Cloud.Puffs[i].Position[1]+Corner2[1]*Cloud.Puffs[i].Size,
Cloud.Puffs[i].Position[2]+Corner2[2]*Cloud.Puffs[i].Size);
AddToMem(Cloud, j, v2, iv3, pColor, pColor2);
Inc(j);
iv3 := Vector3fMake(Cloud.Puffs[i].Position[0]+Corner3[0]*Cloud.Puffs[i].Size,
Cloud.Puffs[i].Position[1]+Corner3[1]*Cloud.Puffs[i].Size,
Cloud.Puffs[i].Position[2]+Corner3[2]*Cloud.Puffs[i].Size);
AddToMem(Cloud, j, v3, iv3, pColor, pColor2);
Inc(j);
iv3 := Vector3fMake(Cloud.Puffs[i].Position[0]+Corner4[0]*Cloud.Puffs[i].Size,
Cloud.Puffs[i].Position[1]+Corner4[1]*Cloud.Puffs[i].Size,
Cloud.Puffs[i].Position[2]+Corner4[2]*Cloud.Puffs[i].Size);
AddToMem(Cloud, j, v4, iv3, pColor, pColor2);
Inc(j);
End;
end;


Many Thanks
Nic

M109uk
15-11-2007, 07:57 PM
Im completly stumped now,

If it helps, i have updated the ZIP file (as mentioned before).

Many thanks
Nic

Robert Kosek
16-11-2007, 02:11 AM
I'm afraid this is the limit of my knowledge here. I was thinking pointers might speed things, but I really just don't know. Maybe for functionality and ease of maintenance you should just stick with arrays.

M109uk
16-11-2007, 07:37 AM
Ok many thanks anyway :)

i think i shall start from the beginning and try converting it without GLScene for now.

I shall post the demo if im successfull :)

Thanks again
Nic