Register forum user name Search FAQ

Gammon Forum

Notice: Any messages purporting to come from this site telling you that your password has expired, or that you need to verify your details, confirm your email, resolve issues, making threats, or asking for money, are spam. We do not email users with any such messages. If you have lost your password you can obtain a new one by using the password reset link.

Due to spam on this forum, all posts now need moderator approval.

 Entire forum ➜ MUSHclient ➜ Miniwindows ➜ Miniwindows showcase (has a lot of graphics)

Miniwindows showcase (has a lot of graphics)

It is now over 60 days since the last post. This thread is closed.     Refresh page


Pages: 1  2 

Posted by Nick Gammon   Australia  (23,133 posts)  Bio   Forum Administrator
Date Reply #15 on Sat 05 Jun 2010 10:54 PM (UTC)

Amended on Sat 05 Jun 2010 11:11 PM (UTC) by Nick Gammon

Message
I can't get the 3D mapper to work right now (mainly because of the horrible way I was getting the mapping data into it), but this snippet (which you can run in the Immediate window) actually draws one 3D scene which a constant at the start of it. To try it out you need the texture files, which I don't want to supply because I'm not sure of the copyright. But it shows the general idea.


-- 3D mapper test 
-- Written by Nick Gammon 
-- Date: August 2008

-- test map

map = [==[
         ---     ---        
        |{+} {!} {+}|     
     -------     ---|        
    +{+} {+} {+} {+>|     
     -------     ---         
         [?] <!> [?]      
                 ---         
         [?] <#> < . [?]  
                 ---         
         [?] < > [?]      
     -------     -------     
     - - -!- < > -*- - -  
     -------     -------     
            |. .|    
          
            
                   
]==]


local mapWidth = 80
local mapHeight = 80

local texWidth = 64
local texHeight = 64

posX = 35; posY = 35;  --x and y start position
dirX = 0; dirY = -1; --initial direction vector
planeX = -0.7853; planeY = 0; --the 2d raycaster version of camera plane

HEIGHT_MULTIPLIER = 4

dir = "/Program Files/mushclient/"
  
require "tprint"
require "getlines"


-- make local for speed

local floor = math.floor
local ceil = math.ceil
local abs =  math.abs
local sqrt =  math.sqrt
local cos = math.cos
local sin = math.sin

local WindowLine = WindowLine

local function int (x)
  if x >= 0 then
    return floor (x)
  end  -- if positive

  return ceil (x)
end -- function int

function setup_map_window ()
  

  WINDOW_HEIGHT = 300
  WINDOW_WIDTH = 400 -- 320
  
  win = "3d"
  wins = "3dshadow"
  
  -- how many pixels per tile
  
  tilewidth = WINDOW_WIDTH / mapWidth
  tileheight = WINDOW_HEIGHT / mapHeight
  
  WindowCreate (win, 
    0, -- left
    0, -- top
    WINDOW_WIDTH, -- width
    WINDOW_HEIGHT, -- height
    8, -- mode
    0, -- flags
    0x383838)
  
  WindowCreate (wins, 
    0, -- left
    0, -- top
    WINDOW_WIDTH, -- width
    WINDOW_HEIGHT, -- height
    8, -- mode
    0, -- flags
    0xFFFFFF)
        
  WindowShow (win, true)
  
  local pencolour = 0x555555
  local centre = WINDOW_HEIGHT / 2
  
  -- sky
  WindowGradient (win, 0, 0, 0, centre, 
                  0xFFBF00,
                  ColourNameToRGB ("darkblue"), 
                  2)  -- top to bottom
  
  -- ground
  WindowGradient (win, 0, centre, 0, 0, 
          0x00091C, 
          ColourNameToRGB ("lightsalmon"), 
          2)  -- top to bottom
          
  -- noise        
  WindowFilter (win, 0, 0, 0, 0, 2, 15)
  
  WindowRectOp (win, 1,   -- frame rectangle
            0, 0, 
            0, 0, 
            0x00002F)
        
  images = {
      "eagle",        -- 1
      "redbrick",     -- 2
      "purplestone",  -- 3
      "greystone",    -- 4
      "bluestone",    -- 5
      "mossy",        -- 6
      "wood",         -- 7
      "colorstone",   -- 8
    }
  
  check (WindowLoadImage (win, "eagle", dir .. "eagle.bmp"))  
  check (WindowLoadImage (win, "redbrick", dir .. "redbrick.bmp"))
  check (WindowLoadImage (win, "purplestone", dir .. "purplestone.bmp"))
  check (WindowLoadImage (win, "greystone", dir .. "greystone.bmp"))
  check (WindowLoadImage (win, "bluestone", dir .. "bluestone.bmp"))
  check (WindowLoadImage (win, "mossy", dir .. "mossy.bmp"))
  check (WindowLoadImage (win, "wood", dir .. "wood.bmp"))
  check (WindowLoadImage (win, "colorstone", dir .. "colorstone.bmp"))
 
end -- setup_map_window

local colour_map = {
    [1] = ColourNameToRGB ("red"),
    [2] = ColourNameToRGB ("green"),
    [3] = ColourNameToRGB ("blue"),
    [4] = ColourNameToRGB ("white"),
    } -- end colour_map
    
        
local function hwall (wx, wy, which)
  for i = wx, wx + 9 do
    worldMap [i] [wy] = which
  end -- for
end -- hwall

local function vwall (wx, wy, which)
  for i = wy, wy + 9 do
    worldMap [wx] [i] = which
  end -- for
end -- hwall

    
function convert_map ()
  
  -- empty table
  maprooms = {}
  for x = 1, 8 do
    maprooms [x] = {}
  end -- for each x
  
  mapline = {}
  
  x = 1
  for line in getlines (map) do
    mapline [x] = line
    x = x + 1
  end -- for
  
  -- bleecccchh
  
  for x = 1, 8 do  
    for y = 1, 8 do
      local t = {}
      maprooms [x] [y] = t
      t.top = mapline [y * 2 - 1]:sub ((x - 1) * 4 + 1, (x - 1) * 4 + 5)
      t.middle = mapline [y * 2    ]:sub ((x - 1) * 4 + 1, (x - 1) * 4 + 5)
      t.bottom = mapline [y * 2 + 1]:sub ((x - 1) * 4 + 1, (x - 1) * 4 + 5)
    end -- each y
  end -- each x

  
  worldMap = {}
  
  for x = 1, mapWidth do
    local t = {}
    worldMap [x] = t
    for y = 1, mapHeight do
       t [y] = 0  -- nothing there yet
    end -- for
  end -- for
  
  for x = 1, 8 do  
    for y = 1, 8 do
      t = maprooms [x] [y]
      local wx = (x - 1) * 10 + 1
      local wy = (y - 1) * 10 + 1
     
      if t.top:sub (2, 3) == "--" then
        hwall (wx, wy, 4)
      end -- if
  
      if t.bottom:sub (2, 3) == "--" then
        hwall (wx, wy + 9, 4)
      end -- if

      if t.top:sub (2, 3) == "-+" then
        hwall (wx, wy, 2)
      end -- if

      if t.bottom:sub (2, 3) == "-+" then
        hwall (wx, wy, 2)
      end -- if

      if t.middle:sub (-1) == "|" then
        vwall (wx + 9, wy, 4)
      end -- if
      
      if t.middle:sub (1, 1) == "|" then
        vwall (wx, wy, 4)
      end -- if
       
      if t.middle == " [?] " then
        vwall (wx, wy, 7)
        vwall (wx + 9, wy, 7)
      end -- if
           
    end -- each y
  end -- each x  
     
end -- convert_map    

texture = {}
for x = 1, 64 do
  texture [x] = {}
  for y = 1, 64 do
    local c = bit.xor (x, y)
    texture [x] [y] = c + c * 0x000200 + x * 0x010000
  end -- for
end -- for

function Display_Map ()

  convert_map ()
  
  setup_map_window ()

  local w = WINDOW_WIDTH
  local h = WINDOW_HEIGHT
  
  for x = 0, w - 1 do
    --calculate ray position and direction 
   local cameraX = 2 * x / w - 1 --x-coordinate in camera space
   local rayPosX = posX
   local rayPosY = posY
   local rayDirX = dirX + planeX * cameraX
   local rayDirY = dirY + planeY * cameraX
    
  --which box of the map we're in  
  
   local mapX = int (rayPosX)
   local mapY = int (rayPosY)
     
    --length of ray from current position to next x or y-side
    local sideDistX
    local sideDistY
     
     --length of ray from one x or y-side to next x or y-side
    local deltaDistX = sqrt (1 + (rayDirY * rayDirY) / (rayDirX * rayDirX))
    local deltaDistY = sqrt (1 + (rayDirX * rayDirX) / (rayDirY * rayDirY))
    local perpWallDist
     
    --what direction to step in x or y-direction (either +1 or -1)
    local stepX
    local stepY

    local hit = false  --was there a wall hit?
    local YsideHit --was a NS or a EW wall hit?
    
    -- calculate step and initial sideDist
    
    if rayDirX < 0 then
      stepX = -1
      sideDistX = (rayPosX - mapX) * deltaDistX
    else
      stepX = 1
      sideDistX = (mapX + 1.0 - rayPosX) * deltaDistX
    end -- if
    
    if rayDirY < 0 then
      stepY = -1
      sideDistY = (rayPosY - mapY) * deltaDistY
    else
      stepY = 1
      sideDistY = (mapY + 1.0 - rayPosY) * deltaDistY
    end -- if
        
   --perform DDA
   while not hit do
    
    --jump to next map square, OR in x-direction, OR in y-direction
    if sideDistX < sideDistY then
      sideDistX = sideDistX + deltaDistX
      mapX = int (mapX + stepX)
      YsideHit = false
    else
      sideDistY = sideDistY + deltaDistY
      mapY = int (mapY + stepY)
      YsideHit = true
    end -- if
    
    if mapX < 0 or 
       mapY < 0 or
       mapX > mapWidth or
       mapY > mapHeight then
       break
     end -- outside map
       
    if worldMap[mapX] == nil then
      break
    end -- if off map  
    
   if worldMap[mapX] [mapY] == nil then
      break
    end -- if off map  
    
    --Check if ray has hit a wall
    if worldMap[mapX][mapY] > 0 then
     hit = true
    end -- if hit
    
  end -- while 
  
 local wallX --where exactly the wall was hit
 local drawEnd
     
   --calculate value of wallX
    
    if YsideHit then
      wallX = rayPosX + ((mapY - rayPosY + (1 - stepY) / 2) / rayDirY) * rayDirX
    else       
      wallX = rayPosY + ((mapX - rayPosX + (1 - stepX) / 2) / rayDirX) * rayDirY
    end -- if 
    
    -- Calculate distance projected on camera direction (oblique distance will give fisheye effect!)
    
    if not YsideHit then
      perpWallDist = abs ((mapX - rayPosX + (1 - stepX) / 2) / rayDirX)
    else
      perpWallDist = abs ((mapY - rayPosY + (1 - stepY) / 2) / rayDirY)
    end -- if
 
      
    --Calculate height of line to draw on screen
    local lineHeight = int (abs  (h / perpWallDist) * HEIGHT_MULTIPLIER)
     
    --calculate lowest and highest pixel to fill in current stripe
    local drawStart = -lineHeight / 2 + h / 2
    if drawStart < 0 then
      drawStart = 0
    end -- if
    
    drawEnd = lineHeight / 2 + h / 2
    if drawEnd >= h then
      drawEnd = h - 1
    end -- if
    
   local adjwallX = wallX / 10
   adjwallX = adjwallX - floor((adjwallX))

   if hit then
 
      --texturing calculations
      local texNum = worldMap [mapX][mapY]
       
      --x coordinate on the texture
      local texX = int (adjwallX * texWidth)
      
      if (not YsideHit) and (rayDirX > 0) then
         texX = texWidth - texX - 1
      end -- if
       
      if YsideHit and (rayDirY < 0) then
       texX = texWidth - texX - 1
      end -- if
      
      check (WindowDrawImage(win, images [texNum], x + 1, drawStart , x + 2, drawEnd, 
             2, 
              texX, 0, texX + 1, 0))
          
      check (WindowFilter (win,  x + 1, drawStart , x + 2, drawEnd, 7, -perpWallDist * 4)) -- darken
      
      if x >  w / 2 then
        check (WindowFilter (win,  x + 1, drawStart , x + 2, drawEnd, 9, 1.4)) -- gamma (darken)
      else
        check (WindowFilter (win,  x + 1, drawStart , x + 2, drawEnd, 9, .8)) -- gamma (lighten)
      end -- if on RH side
               
   end -- of hit on wall
   
    --FLOOR CASTING

    local floorXWall, floorYWall -- x, y position of the floor texel at the bottom of the wall

    --4 different wall directions possible
    
    if not YsideHit and (rayDirX > 0) then
      floorXWall = mapX
      floorYWall = mapY + wallX
    elseif not YsideHit and (rayDirX < 0) then
      floorXWall = mapX + 1.0
      floorYWall = mapY + wallX
    elseif YsideHit and (rayDirY > 0) then
      floorXWall = mapX + wallX 
      floorYWall = mapY
    else
      floorXWall = mapX + wallX 
      floorYWall = mapY + 1.0
    end -- if
        
    local distWall, currentDist  

    distWall = perpWallDist
   
    if drawEnd < 0 then
      drawEnd = h -- becomes < 0 when the integer overflows
    end -- if
    
    --draw the floor from drawEnd to the bottom of the screen
    for y = int (drawEnd + 1), h do
      currentDist = h / (2 * y - h) -- you could make a small lookup table for this instead
      
      --floor
      WindowSetPixel (win, x, y, 0x0000FF / currentDist)
     
      -- ceiling (symmetrical!)
      WindowSetPixel (win, x, h- y, int (256 / currentDist) * 256)
      
    end -- for loop
         
    -- shadow
    
    if x > w / 2 then
      WindowLine(wins, x + 1, drawEnd , x - abs (drawStart - drawEnd), drawEnd, 0x777777, 0, 1)
    end -- if 
        
  end -- for each x
  
  WindowFilter(wins, 0, 0, 0, 0, 3, 0)
  WindowImageFromWindow (win, "shadows", wins)
  
  WindowBlendImage (win, "shadows", 4, 0, 0, 0, 6, 1)

end -- Display_Map

Display_Map ()



That's under 500 lines of Lua code to render a 3D window.

Below is the output as rendered by the above code.

That took 0.17 seconds to do the Display_Map part.

- Nick Gammon

www.gammon.com.au, www.mushclient.com
Top

Posted by Nick Gammon   Australia  (23,133 posts)  Bio   Forum Administrator
Date Reply #16 on Sat 05 Jun 2010 10:58 PM (UTC)
Message


- Nick Gammon

www.gammon.com.au, www.mushclient.com
Top

Posted by Nick Gammon   Australia  (23,133 posts)  Bio   Forum Administrator
Date Reply #17 on Sat 05 Jun 2010 11:13 PM (UTC)
Message
The image files are basically 64 x 64 pixel 24 bits-per-pixel bitmap (bmp) files, so any file along those lines should be OK if you want to try to run it.

- Nick Gammon

www.gammon.com.au, www.mushclient.com
Top

Posted by Nick Gammon   Australia  (23,133 posts)  Bio   Forum Administrator
Date Reply #18 on Sun 06 Jun 2010 05:37 AM (UTC)

Amended on Sun 06 Jun 2010 06:01 AM (UTC) by Nick Gammon

Message

I think I got a lot of inspiration from here:

http://www.student.kuleuven.be/~m0216922/CG/raycasting.html

and:

http://www.student.kuleuven.be/~m0216922/CG/raycasting2.html

I think you can also download the graphics files (textures) from that page too.


- Nick Gammon

www.gammon.com.au, www.mushclient.com
Top

The dates and times for posts above are shown in Universal Co-ordinated Time (UTC).

To show them in your local time you can join the forum, and then set the 'time correction' field in your profile to the number of hours difference between your location and UTC time.


76,670 views.

This is page 2, subject is 2 pages long:  [Previous page]  1  2 

It is now over 60 days since the last post. This thread is closed.     Refresh page

Go to topic:           Search the forum


[Go to top] top

Information and images on this site are licensed under the Creative Commons Attribution 3.0 Australia License unless stated otherwise.