ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿ 80x50! ³ ® How to make a 3D texture mapped tunnel effect ¯ ³ ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ ... by Il£vatar of Nordic Line (a.k.a. Kari Salminen) 060795 BTW this the first documentation for an effect I have ever written, because usually I just keep those thingies in my mind and don't release them... It's 6:30 am at the time I'm writing this so let's get to the point... First you'll need about 128Kb of free memory for the precalculations... ;) Check... Ok. Then you need a nice 256x256/256c. picture to be the texture map... Check... Ok. So far so fine - but how is the effect done... Ok, a little piece of maths is coming right up... I suppose that you know the common perspective projection that is : (Some variables first though...) Xp,Yp = Projected X and Y-coordinates X,Y,Z = The original coordinates of a 3D point D = Eye's distance from the projection plane P = Projection plane = screen (Only needed for the picture) We can derive from the picture's similar triangles the following stuff : (Hey you there look at the nice ascii triangles below!) Y Yp ³ Y*D ÄÄÄ = ÄÄÄ ³*D --> ÄÄÄ = Yp D+Z D ³ D+Z /³ So the Y-perspective projection calculation is : / ³³ / ³³ Yp = Y*D/(D+Z) / ³³ / ³³ And the X is calculated similarly : / ³³ / ³³ Xp = X*D/(D+Z) / ³³ /³³ ³³ Check... Ok. / ³³ ³³ / ³ ³ / ³Yp ³Y / ³ ³ / ³³ ³³ / ³³ ³³ / ³ ³³ ÄÄÄÄÄÄÄÄÁÄÄÄÄÄÄÄÙ <--D-->P<--Z--> And I suppose that you know something about radians and trigonometry too. (More ascii art coming up...) In a circle with a radius of 1 the X-coordinate is cosà and the Y-coordinate is sinà... simple 8:) ³\ Usually cosà=b/c and sinà=a/c but when c=1 then ³ \ cosà=b/1 and sinà=a/1 so it all comes down to ³ \ c=radius cosà=b and sinà=a and yet more simplified ³ \ cosà=x and sinà=y... great ;) a=y³ \ ³ \ Check... Ok. ³ \ ³ à\ ÀÄÄÄÄÄÄÄÄ b=x Now you know all the basic math to begin to make the tunnel effecto... The tunnel is an infinite series of circles repeated another after another. So now we have to make a mathematical equation for the tunnel... Let's give it a shot! (BOOM!) BTW : We can discard the D from the D+Z (divider) of the perspective projection equation. So Xp = X*D/(D+Z) comes Xp = X*D/Z and Yp = Y*D/(D+Z) comes Yp = Y*D/Z, this is sufficient for the tunnel calculation and works fine otherwise too. R = Constant radius of the tunnel (Determined by YOU!). D = Eye's constant distance from the screen (Determined by YOU!). You can try different values for R and D but I suggest that something from 32 to 256 are good values for R and D. More math coming up... COSà*R*D ÄÄÄÄÄÄÄÄ = Xp (Equation for the projected X-coordinate on the tunnel wall) Z SINà*R*D ÄÄÄÄÄÄÄÄ = Yp (Equation for the projected Y-coordinate on the tunnel wall) Z What we now need is the à (angle) and the Z (depth)... Let's first solve the Z... (You can use the equation with SINà too, if you like to.) COSà*R*D ³ ³ COSà*R*D ÄÄÄÄÄÄÄÄ = Xp ³*Z --> Xp*Z = COSà*R*D ³:Xp --> Z = ÄÄÄÄÄÄÄÄ Z ³ ³ Xp Ok... And now going for the angle! COSà*R*D SINà*R*D ³ COSà SINà ³ COSà*Yp ³ ÄÄÄÄÄÄÄÄ = ÄÄÄÄÄÄÄÄ ³:R*D --> ÄÄÄÄ = ÄÄÄÄ ³*Yp --> ÄÄÄÄÄÄÄ = SINà ³:COSà Xp Yp ³ Xp Yp ³ Xp ³ Yp SINà Yp Yp ÄÄ = ÄÄÄÄ --> ÄÄ = TANà --> à = ATAN ÄÄ Xp COSà Xp Xp Math equations... Check... Ok. Now you just go thru the whole screen from -WIDTH/2 TO WIDTH/2-1 for the X and -HEIGHT/2 TO HEIGHT/2-1 for the Y. For a 320x200 screen you would go from -160 to 159 for the X and from -100 to 99 for the Y. And for every pixel you calculate the following : Y à = ATAN Ä (Calculate this first for every pixel) X When you calculate this value, the ARCTAN function of you favorite programming language will give the angle in radians _VERY_ probably. So we need to convert the à from radians to degrees with 256 angles circle. That is done by multiplying the à by half of the angles in the circle and dividing this by ã (pi) --> à = ARCTAN(Y/X)*(256/2)/ã. ^^^^^^^^^^^^^^^^^^^^^^^^^^ This is the angle in the tunnel wall at the current pixel. So what do we do with it? We must have already allocated a 64Kb precalculation table for the angles... So we store this value in the table at the position X+WIDTH/2+(Y+HEIGHT/2)*WIDTH... Simple. With a 320x200 screen we would put the value to X+160+(Y+100)*320. Remember that X goes from -160 to 159 and Y from -100 to 99. Angle takes values 0-255. We can think of the angle as the X-texture coordinate, so increasing the texture X-coordinate would rotate the tunnel. COSà*R*D Z = ÄÄÄÄÄÄÄÄ (Calculate this too for every pixel) X Because we have just calculated the à we can put it in this equation and voila! It works... (BTW : You _MUST_ use the radian version of the just calculated angle value, because SIN and COS functions need their parameters in radians. So you should convert angle to degrees only after you have calculated this Z-value!) Now we have the Z value too... We must have already allocated a 64Kb precalculation table for the depths too... Now we put this value in the table at the position X+WIDTH/2+(Y+HEIGHT/2)*WIDTH... With a 320x200 screen we would put the value to X+160+(Y+100)*320. Remember that X goes from -160 to 159 and Y from -100 to 99. Depth takes values 0-255. We can think of the depth value as the Y-texture coordinate, so increasing the texture Y-coordinate would zoom in the tunnel. Once we have gone all this precalculating we just do this : We go from 0 to WIDTH-1 for X and from 0 to HEIGHT-1 for Y and look up the X-texture coordinate from the angle-lookup-table and look up the Y-texture coordinate from the depth-lookup-table. If we want to rotate or zoom the tunnel we can add texture-x-adder to the retrieved angle value and texture-y-adder to the retrieved depth value. Then we just take the pixel from the texture map at the retrieved X and Y coordinates and put it onscreen, voila! A rotating and zooming 3D texture mapped tunnel with a _FAST_ method... (Needs a bit of precalculating though...;)) An example in Pascal : for y:=0 to 199 do for x:=0 to 319 do begin texture_x:=(angles[x+y*320]+texture_x_adder) and 255; texture_y:=(depths[x+y*320]+texture_y_adder) and 255; video_screen[x+y*320]:=texture_map[texture_x+texture_y*256]; end; Quite trivial if I wouldn't say... PS. There can be some messing around with the arcus tangent function, because when I precalculated the angles with Pascal, the tunnel went partly to the wrong direction... You can correct this by precalculating only one fourth of the precalculation tables and by flipping and mirroring that data to construct the other three fourths of the precalculation table. Have fun! This fast (And quite crappy too I think) explanation of a 3D tunnel effect was done by Il£vatar of Nordic Line (a.k.a. Kari Salminen). I was first inspired by the CapaCala's "The Real Thing" demo's sewer zoomer part. So I went on and thought of ways of doing such an effect and came up with this one. After that I have seen this kind of effect in Napalm's "Noname00" and Fascination's "Hive" (With some crossfading added though) and in one demo by Ground Zero... If you want to contact me for some strange reason : You can e-mail me at : ksalmi@kummeli.edutec.pori.fi (Primary) kari.salminen@under.nullnet.fi (Secondary) Or snail mail me at : Kari Salminen Patsaskuja 17 29600 Noormarkku Finland There can be some typos in the text so if something looks _HORRIBLY_ wrong then it probably is. After all I hope you figured out those things that I wrote about... If you didn't you can always send me a letter or an e-mail. Hope this helped! Have fun and live long (and prosper ;)) Clock check... 9:19 am, I must be off to sleep now... Bye! Il£vatar of Nordic Line 060795