#### Archived

This topic is now archived and is closed to further replies.

# 3D raycasting engine in java-script/DHTML...

This topic is 5707 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

## Recommended Posts

current version is http://www.elephantsneverforget.co.uk/rg/gmen.asp [edited by - robertgamble on July 3, 2002 4:28:01 AM]

##### Share on other sites
That''s pretty neat !

quote:

96 + (224-191)/Math.tan(60), should be about 115 right?

Uh, are you sure that Math.tan() expects the parameter to be in degrees, and not in radians ? In the later case, the result would be 199.11

##### Share on other sites
Neither of those links work in galeon(gecko/ns6 based browser).

Pitty, sounded interesting.

##### Share on other sites
It worked in Mozilla the last time I tried, but now it''s broken. I guess he changed something that broke the compatibility ?

##### Share on other sites
It is waaaay (Waaay) too slow to use in anything but IE.. I had it working in Mozilla but it was atleast 20 times slower than IE

Yann L, hey you''re right I feel silly now, thanks for that

##### Share on other sites
That''s pretty nifty. I think java-script is an area where the old optimization tricks come in handy. Avoid modulus operators when possible, avoid division when possible, definitely remove them from loops. Use multiplication and addition instead when possible. The judicious use of bitmasks and bitshifts can also help. Unrolling loops can result in speed increases as well. I''ve found that sets of 8 work very well - but coding them up can be a pain. I haven''t done any java-scripting lately - so I can''t speak as directly regarding the document object model and so forth as I once was able to - but in the past I found that setting up all the containers during initialization and then tweeking their parameters during execution produced better results than rebuilding them as strings and then "blitting" them (so to speak). Especially if the total number of containers is constant or isn''t too large. The definition of "too large" varies according to the machine.

I wasn''t able to get either version to work correctly in Mozilla. Works fine in IE though. Keep up the good work!

##### Share on other sites
Yeah, I''ve used loop unrolling before.. It did seem to give a bit of a speed increase. But you''re right, writing it would be a pain.. Resizing and moving objects did seem a bit faster than "blitting" them every frame.

I''ve started on a new version http://www.elephantsneverforget.co.uk/hroberts/editor/gmen.asp, but I can''t get it to display stuff properly. Even without any optimisations at all it seems waaay faster than the other one though. I''d be really grateful if someone could take a quick look through the source and see if they can spot whats wrong. Cheers..

##### Share on other sites
You might want to check out these "the5k" entries... they are all java-script raycasters:

http://www.the5k.org/description.asp/entry_id=946
http://www.the5k.org/description.asp/entry_id=1283
http://www.the5k.org/description.asp/entry_id=1302

##### Share on other sites
quote:
Original post by robertgamble
I''d be really grateful if someone could take a quick look through the source and see if they can spot whats wrong. Cheers..

It''s faster. It still doesn''t work in Mozilla. I looked through the source but I don''t have as keen an eye for js as I used to so I didn''t spot anything wrong.

##### Share on other sites
Works in Mozilla now (and is very fast too!), still can''t get it to work properly though. I think the problem is here:

 //find first x intersection (vert) ray.vx=(correct<0)?Math.floor(player.x/map.scale) * (map.scale) - 1:Math.floor(player.x/map.scale) * (map.scale) + map.scale; vxa=(correct<0)?-map.scale:map.scale; //find first y intersection (vert) ray.vy = player.y + (player.x-ray.x)*Math.tan(rad(ang)); vya=map.scale*Math.tan(rad(ang));

But I really don''t know

I looked at those contest entries, but sadly I don''t think they''ll be much help Thanks though.

##### Share on other sites
I don''t have any solution to your problem, but you shouldn''t start optimizing right now. Clean up the code, and make it work first.

In case you get it to work, I''d recommend you to create a lookup-table for your tan''s with angles converted. Also, don''t use sqrt for your distance (it''s way too slow)! "(ray.x - player.x) * cos(player.angle) + (ray.y - player.y) * sin(player.angle)" works as well, and gets rid of the fish-eye effect.

##### Share on other sites
Yeah sqrt is probably a little too slow

I''ll use the other method once I''ve got this thing to display properly, aswell as use the lookup tables in the raycasting loop.

I think I''m a tiny bit closer to getting it right. If you spin around you can see walls and corners, etc. But alot of the time stuff is being calculated completely wrongly! Grrr..

##### Share on other sites
Yes, much faster and works in Mozilla too.

##### Share on other sites
Fixed it up good and proper (ish!).

http://www.elephantsneverforget.co.uk/rg/gmen.asp

+ "command line" options

textures=true/false, to turn texture mapping on (default is off)
drawdist=x, sets the draw distance to x (0 = far away, 100 = right near you)

I.E only stuff (do filters work in Mozilla?)
fog=true/false, to turn fog on (default is off)
blur=true/false, to turn blurring on (default is off).

So to turn textures and fog on you do: http://www.elephantsneverforget.co.uk/rg/gmen.asp?textures=true&fog=true

Could anyone suggest a better way of doing textures? Mine''s very wrong.. Can floor textures be done without rotating images?

I can''t get this:
"(ray.x - player.x) * cos(player.angle) + (ray.y - player.y) * sin(player.angle)"

..to work

##### Share on other sites
I don''t know about filters in Mozilla, but now it runs faster in Mozilla than it does in IE.

I think you should turn the textures on by default. This is the first version that looked like a ray caster to me! The others looked like cross sections of an axle. Adding a floor and a ceiling will probably help in that regard too. Some of the wall textures don''t load until they come into view. You might consider preloading an image array to work around this. That might also help with the floor rotations.

Looking good!

##### Share on other sites
I''ve turned textures on by default and made a tiny change that seems to have doubled the speed!

I''ll preload the images and rewrite the rendering code a bit. As you mentioned earlier it might be faster to resize & move the DIV tags rather than redraw them every frame.

I''m really doubtful that floor textures are possible. But I''ll look into it. Stairs and variable height walls might be pretty simple, as would bad guys I think I can make this a fully fledged game

##### Share on other sites
Yes, it''s faster in IE now than it was before, but I think it''s still faster in Mozilla.

I would think that changing properties would be faster than creating anew each time. Test it to be certain.

Floor and ceiling are important. You might be able to get away with faking them. Split the view in half at the horizon. Set the color of the upper half to ceiling color, set the lower half to floor color and draw the walls on top of both halves.

##### Share on other sites
Faked the floor with a colored table. It does make quite a difference I think. Though textures would be nicer..

Also new option, you can set the color of the fog.

..gmen.asp?fogcolor=ff99ff

##### Share on other sites
Yes, the floor "grounds" the walls so to speak.

Is it possible to make the view wider?

##### Share on other sites
&view=number

The default is 40 (it was 30 before you mentioned it), I find anything much higher to be too slow.. Also there''s some really horrible bugs in my code that are alot more prominent with a larger view width.

##### Share on other sites
I tried it with 80. Slower, but about the same speed as some of the earlier versions, so good enough for testing.

As for bugs - Mozilla''s java-script console isn''t showing any. The fisheye effect is still there, but not overly pronounced. I suspect that when you get "(ray.x - player.x) * cos(player.angle) + (ray.y - player.y) * sin(player.angle)" figured out that will go away.

##### Share on other sites
I''ve worked out that it should be "Math.abs(ray.x - player.x) * CosTable[ang] + Math.abs(ray.y - player.y) * SinTable[ang]", but it just doesn''t work. Grr... The graphics were really messed up, but it did seem faster.

I might start again and do it properly this time

##### Share on other sites
Have you got a copy of the sources for Mozilla''s implementation of java-script? The Mozilla project is named "spider monkey". At any rate, here is what goes on beneath the hood of the call to Math.abs:

  static JSBoolmath_abs(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval){    jsdouble x, z;    if (!js_ValueToNumber(cx, argv[0], &x))        return JS_FALSE;    z = fd_fabs(x);    return js_NewNumberValue(cx, z, rval);}double fd_fabs(double x){        fd_twoints u;        u.d = x;	__HI(u) &= 0x7fffffff;        x = u.d;        return x;}typedef union {#ifdef __LITTLE_ENDIAN    struct { int lo, hi; } ints;#else    struct { int hi, lo; } ints;#endif    double d;} fd_twoints;#define __HI(x) x.ints.hi#define __LO(x) x.ints.lo

So, while this might not help solve the immediate problem, it might help reduce some overhead afterwards.

##### Share on other sites
OK, here''s the current dist-calculation I use in my raycaster (writing one for TI-calcs):

  ABS(x - playerX) * ABS(cos(playerAngle)) +ABS(y - playerY) * ABS(sin(playerAngle))

Note that it MUST be "playerAngle", otherwise the fisheye-effect won''t be removed. The ABS''s should be removeable somehow (though I need them).

In case it still won''t work, do this to remove the fisheye-blurp:

  distance = ray lengthtracedColumn = which columncorrectDistance = distance * sin(90 - screenWidth/2 + tracedColumn);

Note that the above is in degrees!
The textures look a little funny, are they drawed correctly?

##### Share on other sites
Thanks coelurus,

tmp2=Math.abs(ray.vx - player.x) * CosTable[ang] + Math.abs(ray.vy - player.y) * SinTable[ang]

I should have been using the absolute value of Cos(ang) and sin(ang). So it works now, and seems a tad faster than using sqrt.

The textures are VERY wrong. I think it''s because My columns are 8 pixels wide each. (I''m adding 1 to the ray angle, instead of 0.13 or whatever it should be).