How to move a vertexarray to another point in space?

Hello everyone!

I’m programming a little space sim. Right
now, i’m including planets and i’d like
them to have a nice athmosphere-effect.
Since i have no experience with shader-programming,
i’d like to include a piece of code from the
GLScene “Earth”-Demo in my game. There you
can see the Earth from space with a very nice
athmosphere.

The Atmosphere is a bunch of GL_QUAD_STRIPS and
GL_TRIANGLE_FANS that are originated at (0,0,0).
They build the atmosphere as a kind of sphere
around the sphere that is the earth. Its stored
in “pVertex”.

I would now like to move this atmosphere-sphere
to another point, but i don’t know how, because
i have no experience with 3D-Math.

Hopefully, if i post the source here, somebode
can help me.

(Sorry for my awful english :wink: )

The Source code:

    
procedure TForm1.GLDirectOpenGL1Render(Sender: TObject; var rci: TRenderContextInfo);
const
   // unrealisticly thick atmospheres look better :)
   cAtmosphereRadius : Single = 0.55;
   // use value slightly lower than actual radius, for antialiasing effect
   cPlanetRadius : Single = 0.495;
   cLowAtmColor : TColorVector = (1, 1, 1, 1);
   cHighAtmColor : TColorVector = (0, 0, 1, 1);
   cOpacity : Single = 5;
   cIntDivTable : array [2..20] of Single =
                     (1/2, 1/3, 1/4, 1/5, 1/6, 1/7, 1/8, 1/9, 1/10,
                      1/11, 1/12, 1/13, 1/14, 1/15, 1/16, 1/17, 1/18, 1/19, 1/20);   
var
   radius, invAtmosphereHeight : Single;
   sunPos, eyePos, lightingVector : TVector;
   diskNormal, diskRight, diskUp : TVector;

   function AtmosphereColor(const rayStart, rayEnd : TVector) : TColorVector;
   var
      i, n : Integer;
      atmPoint, normal : TVector;
      altColor : TColorVector;
      alt, rayLength, contrib, decay, intensity, invN : Single;
   begin
      Result:=clrTransparent;
      rayLength:=VectorDistance(rayStart, rayEnd);
      n:=Round(3*rayLength*invAtmosphereHeight)+2;
      if n>10 then n:=10;
      invN:=cIntDivTable[n];//1/n;
      contrib:=rayLength*invN*cOpacity;
      decay:=1-contrib*0.5;
      contrib:=contrib*(1/1.1);
      for i:=n-1 downto 0 do begin
         VectorLerp(rayStart, rayEnd, i*invN, atmPoint);
         // diffuse lighting normal
         normal:=VectorNormalize(atmPoint);
         // diffuse lighting intensity
         intensity:=VectorDotProduct(normal, lightingVector)+0.1;
         if PInteger(@intensity)^>0 then begin
            // sample on the lit side
            intensity:=intensity*contrib;
            alt:=(VectorLength(atmPoint)-cPlanetRadius)*invAtmosphereHeight;
            VectorLerp(cLowAtmColor, cHighAtmColor, alt, altColor);
            Result[0]:=Result[0]*decay+altColor[0]*intensity;
            Result[1]:=Result[1]*decay+altColor[1]*intensity;
            Result[2]:=Result[2]*decay+altColor[2]*intensity;
         end else begin
            // sample on the dark sid
            Result[0]:=Result[0]*decay;
            Result[1]:=Result[1]*decay;
            Result[2]:=Result[2]*decay;
         end;         
      end;
      Result[3]:=n*contrib*cOpacity*0.1;
   end;

   function ComputeColor(var rayDest : TVector; mayHitGround : Boolean) : TColorVector;
   var
      ai1, ai2, pi1, pi2 : TVector;
      rayVector : TVector;
   begin
      rayVector:=VectorNormalize(VectorSubtract(rayDest, eyePos));
      if RayCastSphereIntersect(eyePos, rayVector, NullHmgPoint, cAtmosphereRadius, ai1, ai2)>1 then begin
         // atmosphere hit
         if mayHitGround and (RayCastSphereIntersect(eyePos, rayVector, NullHmgPoint, cPlanetRadius, pi1, pi2)>0) then begin
            // hit ground
            Result:=AtmosphereColor(ai1, pi1);
         end else begin
            // through atmosphere only
            Result:=AtmosphereColor(ai1, ai2);
         end;
         rayDest:=ai1;
      end else Result:=clrTransparent;
   end;

const
   cSlices = 60;
var
   i, j, k0, k1 : Integer;
   cosCache, sinCache : array [0..cSlices] of Single;
   pVertex, pColor : PVectorArray;
   tmp:TVector;
begin
   sunPos:=LSSun.AbsolutePosition;
   eyepos:=GLCamera.AbsolutePosition;

   diskNormal:=VectorNegate(eyePos);
   NormalizeVector(diskNormal);
   diskRight:=VectorCrossProduct(GLCamera.AbsoluteUp, diskNormal);
   NormalizeVector(diskRight);
   diskUp:=VectorCrossProduct(diskNormal, diskRight);
   NormalizeVector(diskUp);

   invAtmosphereHeight:=1/(cAtmosphereRadius-cPlanetRadius);
   lightingVector:=VectorNormalize(sunPos); // sun at infinity
   PrepareSinCosCache(sinCache, cosCache, 0, 360);

   GetMem(pVertex, 2*(cSlices+1)*SizeOf(TVector));
   GetMem(pColor, 2*(cSlices+1)*SizeOf(TVector));

   glPushAttrib(GL_ENABLE_BIT);
   glDepthMask(False);
   glDisable(GL_LIGHTING);
   glEnable(GL_BLEND);
   glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
   for i:=0 to 13 do begin
      if i<5 then
         radius:=cPlanetRadius*Sqrt(i*(1/5))
      else radius:=cPlanetRadius+(i-5.1)*(cAtmosphereRadius-cPlanetRadius)*(1/6.9);
      radius:=SphereVisibleRadius(VectorLength(eyePos), radius);
      k0:=(i and 1)*(cSlices+1);
      k1:=(cSlices+1)-k0;
      for j:=0 to cSlices do begin
         VectorCombine(diskRight, diskUp,
                       cosCache[j]*radius, sinCache[j]*radius,
                       pVertex[k0+j]);

         if i<13 then
            pColor[k0+j]:=ComputeColor(pVertex[k0+j], i<=7);
         if i=0 then Break;
      end;

      if i>1 then begin
         if i=13 then begin
            glBegin(GL_QUAD_STRIP);
            for j:=cSlices downto 0 do begin
               glColor4fv(@pColor[k1+j]);
               glVertex3fv(@pVertex[k1+j]);
               glColor4fv(@clrTransparent);
               glVertex3fv(@pVertex[k0+j]);

            end;
            glEnd;
         end else begin
            glBegin(GL_QUAD_STRIP);
            for j:=cSlices downto 0 do begin

               glColor4fv(@pColor[k1+j]);

               glVertex3fv(@pVertex[k1+j]);
               glColor4fv(@pColor[k0+j]);

               glVertex3fv(@pVertex[k0+j]);
            end;
            glEnd;
         end;
      end else if i=1 then begin
         glBegin(GL_TRIANGLE_FAN);
         glColor4fv(@pColor[k1]);

         glVertex3fv(@pVertex[k1]);
         for j:=k0+cSlices downto k0 do begin
            glColor4fv(@pColor[j]);
           
            glVertex3fv(@pVertex[j]);
         end;
         glEnd;
      end;
   end;
   glDepthMask(True);
   glPopAttrib;

   FreeMem(pVertex);
   FreeMem(pColor);
end; 

You do not need any math knowledge to move your geometry, have a look at transformation in any OpenGL tutorial.

A short hint is to put a glTranslated( x, y, z) before you render your geometry, if you don’t want to mess anything up you can do:

  
glPushMatrix();
glTranslated( x, y, z);
// render your geometry here...
glPopMatrix();

Thank you very much.
It worked within 30 seconds :slight_smile:

Sometimes the solution for a problem
is much more easy than one thinks…