Howdy, Stranger!

It looks like you're new here. If you want to get involved, click one of these buttons!

Raycasting

edited February 2012 in Code Sharing Posts: 159

I've been playing about with raycasting recently, and thought I'd share a video and some code!

At the moment this is just a very basic straight port from a C++ untextured raycaster example I came across (http://lodev.org/cgtutor/raycasting.html). I've also tacked on some terrible touch controls for moving around. It certainly has a couple of bugs when viewing walls at particular angles, etc. It was very easy to port over though, and wouldn't take much work to improve - I just haven't found the time yet! :)

Here's the code: https://gist.github.com/1880241

Tagged:

Comments

  • edited February 2012 Posts: 196

    @frosty - Nice job :) Haven't looked at your code, but just in case setRectTex doesn't just scale the texture and actually displays what is specified in the coordinates, you could easily texture map the wall and it wouldn't be much slower than colored lines since you're using mesh(). Wolfenstein on Codea? ;)

  • I totally would have never used this appoach. (which is why you have something that works and when I tried, I gave up :) )

  • Posts: 2,820

    What is it with 3D things now and days? IT'S AWSOME! I might just turn it into a game with your permission (although I probably won't).

  • Posts: 1,255

    Hey, cool. I was just in the middle of converting a similar bit of code, and now I don't have to. :)

    Looks nice. As @Xavier said, texture draws on mesh surfaces are remarkably fast. Slip mesh.texture = "Planet Cute:Ramp South" in there just for fun.

  • Posts: 447

    Nice! I predict we'll see many first person games in codea using this

  • Posts: 2,820

    Haha... Froggy 3d, snake 3d, breakout 3d... etc. Make the old games 3d!

  • Posts: 447

    Wow this is only 300 lines of lua?! How's that possible...crazy

  • Posts: 159

    @Xavier @Mark Yeah, texture mapping shouldn't be too tricky. You do however need to take into account the exact coordinate at which a ray intersects a wall so you know exactly which part of the texture needs to be displayed. The current untextured version above doesn't do this, but there's code for it in the article I linked in my original post.

    I'm working on writing my own raycaster from scratch (just because I'd like to be able to), and I'm using this tutorial to help me learn: http://www.permadi.com/tutorial/raycast/index.html - it seems to be the tutorial that everyone follows for learning raycasting. It also looks like he addresses how to fix the 'viewing walls at a particular angle causes them to be drawn incorrectly' issue that the code I posted above has.

  • Posts: 1,255

    @frosty Ah, that's a nice one. I'd been trying to make never height surfaces (voxel landscapes) and that original library has some issues when the camera is moved off the plane.

  • Posts: 159

    So I've been having a quick play with very roughly texture mapping this, but I'm having a problem which is probably due to my unfamiliarity with meshes - maybe someone can help...

    I'm trying to texture the walls with the tall stone wall sprite. However, the sprite on its own isn't tall enough (in pixels) to cover the whole height of the wall. Is there a way for me to stretch the sprite so it covers the whole of the mesh rect it's applied to?

  • Posts: 447

    Frosty, yes with setRectTex which allows you do draw only a subregion of the sprite in that rectangle.

    function setup()
        m = mesh()
        m.texture = "Planet Cute:Stone Block Tall"
        local idx = m:addRect(WIDTH/2,HEIGHT/2,WIDTH,HEIGHT)
        m:setRectTex(idx,0,0,1,.94)
    end
    
    function draw()
        background()
        m:draw()
    end
    
  • edited February 2012 Posts: 159

    Thanks, @ruilov - I was nearly there!

    I'm still missing something though. So, I've updated my intialisation of themes meshes like so: (I realise this could be done with a single mesh, but I'm taking baby steps :) )

    idxs = {}
    
    for i = 0, w do
            meshes[i] = mesh()
            meshes[i].vertices = tsq
            meshes[i].texture = "Planet Cute:Stone Block Tall"
            local idx =  meshes[i]:addRect(0, 0, SCALEF, 1)
            
            meshes[i]:setRectTex(idx,0,0,1,.94)
            table.insert(idxs, i, idx)
        end
    

    And then I've altered the drawing code like so:

    pushMatrix()
         meshes[x]:setColors(wcolor)
        
         translate(x, drawStart)
         --scale(1, drawEnd-drawStart)
         meshes[x]:setRect(idxs[x], 0, 0, SCALEF, drawEnd-drawStart)
         meshes[x]:draw()
         popMatrix()
    

    This isn't right, though! Without doing the scale(), each ray isn't tall enough, and stops halfway up the screen. I figured I wouldn't need to scale (and perhaps even not translate) if I could just position the rect through setRect, but I can't quite work out how it should work exactly. Just doing the scale and translate I was doing before isnt right either.

    Any advice? :/

  • edited February 2012 Posts: 159

    Fixed! The main issue was that I hadn't realised that setRect's x and y parameters specify the center of the rect. I was treating them as a corner. I've also changed things so I'm using a single mesh, which results in much faster performance.

    Initialisation:

        rects = {}
        m = mesh()
    
        m.texture = "Planet Cute:Stone Block Tal
        
        for i = 0, w do
            local idx =  m:addRect(0, 0, SCALEF, 1)
            rects[i] = idx
            m:setRectTex(idx,0,0,1,.94)
        end
    

    And drawing is far simpler:

        m:setRectColor(rects[x], wcolor)
        m:setRect(rects[x], x, h/2, SCALEF, drawEnd-drawStart)
    

    With one final call to m:draw() after the main loop.

  • Posts: 159

    Boom! Still needs much work, but I have some proper texture mapping going on!

  • Posts: 1,255

    Wow. You guys are racing ahead. Forget "will it play Doom?" I'm waiting for someone to take this ray caster and make a terrific rogue-like rpg.

  • Minecraft

  • Posts: 2,820

    With time, I would, but with Middle school, time is a thing of the past.

  • Posts: 176
    time is a thing of the past 
    

    I see what you did there, @Zoyt ;-)

  • Posts: 2,820

    Working on better controllers and eventually being put in a class... But I'm barely anywhere. If you were thinking about doing it instead, please do.

  • Great work! I also followed the tutorial, but I can't seem to fix this bug:
    "when viewing walls at particular angles"
    how did you do it?

  • @frosty - Just came across this link. Amazing work - however the link at http://www.permadi.com/tutorial/raycast/index.html is no longer active, do you have an alternate link or a saved copy of that page I could access?

    TIA

    Jon...

Sign In or Register to comment.