Author Topic: Real Time 3D Interiors  (Read 6515 times)

0 Members and 1 Guest are viewing this topic.

Offline rain_storm

  • Here comes the Rain
  • DBF Aficionado
  • ******
  • Posts: 3088
  • Karma: 182
  • Rain never hurt nobody
    • View Profile
    • org_100h
Real Time 3D Interiors
« on: December 28, 2006 »
Okay this is something I've been at for a while now and I think I'm finally on to something,
Originally my 3D engines where a marriage between the old familiar WORMS demo and the 3D CUBE demo that were included in the PS2 yabasic. Basically the collision map (grid(x, y) in the WORMS demo) held the centre point for the cube which was replotted and redrawn for each grid entry that was considered a wall. That technique yielded some results (25 fps on the PS2 when the grid was a 16x16 array). The were however some short-commings with this approach. The cubes often vanished when you stood with your shoulder to the wall such that your line of sight was paralelle with the wall, this left half the screen taken up with the background when surely there should have been a wall.
 This time I have opted for a different approach. The collision map is only used for detecting collisions and a polygon mesh is used to define the rooms appearance. It was necessary to weed out the non visible walls. To achieve this I calculated the crossproduct of each point relative to both the left extreme of vision and the right extreme of vision. Any wall which had one point within the field of view and one point outside the FOV would have to be cropped. Now we cast out two rays (one for each extreme of vision) & calculate the intersection points. Up to now everything is done in 2D. All that is left is to rotate whats the scene, add a vertical dimension and apply perspective.
 I haven't yet checked out the fps for this algorithm but it doesn't suffer any slowdown (at least not noticeably). I still have to sort out a bug in the lighting effects and everything still has to be cleaned up a lot. But it works... Now where do I go from here?
Code: [Select]
init_game()

label game
 draw_grid(grid)
 ctrl = peek("port1")
 if (ctrl <> 0) ctrl_user(ctrl)
 goto game

sub draw_grid(grid) local x, y, w
 if (intro <= 3) then
  setrgb 1, 255, 255, 000
  text 0,240, message$(intro), "cc"
  count = count + 1
  if (count > display) then
   count = 0
   intro = intro + 1
  fi
 fi
 setdispbuf draw
 draw = 1 - draw
 setdrawbuf draw
 horizon =-256*tn(rotx(0))*2
 setrgb 1, 255,255,255
 setrgb 2, 255,255,255
 setrgb 3, 000,000,000
 gtriangle -320,-256 to 320,-256 to 320,horizon
 setrgb 2, 000,000,000
 gtriangle -320,-256 to -320,horizon to 320,horizon
 setrgb 1, 255,000,000
 setrgb 2, 255,000,000
 setrgb 3, 000,000,000
 gtriangle -320,256 to 320,256 to 320,horizon
 setrgb 2, 000,000,000
 gtriangle -320,256 to -320,horizon to 320,horizon

 for w = 1 to walls
  if (tz(w,1) > 0) and (tz(w,3) > 0) then
   lt1 = lt1(w)
   lt2 = lt2(w)
   setrgb 1, red(w)*lt1, grn(w)*lt1, blu(w)*lt1
   setrgb 2, red(w)*lt1, grn(w)*lt1, blu(w)*lt1
   setrgb 3, red(w)*lt2, grn(w)*lt2, blu(w)*lt2
   gtriangle tx(w,1),ty(w,1) to tx(w,2),ty(w,2) to tx(w,3),ty(w,3)
   setrgb 2, red(w)*lt2, grn(w)*lt2, blu(w)*lt2
   gtriangle tx(w,1),ty(w,1) to tx(w,4),ty(w,4) to tx(w,3),ty(w,3)
  fi
 next
 for y = 1 to gridy
  for x = 0 to gridx
   if (grid(x, y) <> 0) then
    if    (grid(x, y) = wall) then setrgb 1, 100, 100, 100
    elsif (grid(x, y) = door) then setrgb 1, 200, 120, 080
    fi
    fill box x*m-300, y*m-240 to x*m+m-300, y*m+m-240
   fi
  next
 next
 setrgb 1, 000,000,255
 fill circle posx(0)*m-300, posy(0)*m-240, m/2
end sub

sub rota_grid()
 cx = -cs(rotx(0))
 sx = -sn(rotx(0))
 cy = -cs(roty(0))
 sy = -sn(roty(0))
 cz = -ct(rotz(0))
 sz = -tn(rotz(0))
 posx = posx(0)*m
 posy = posy(0)*m
 posz = posz(0)*m
 for w = 1 to walls
  px = ix1(w)*m-posx
  py = iy1(w)*m-posy
  pz =-m/2-posz
  nx = cz*px + sz*py
  ny = cz*py - sz*px
  nz = cy*pz + sy*nx
  tx = cy*nx - sy*pz
  ty = cx*ny + sx*nz
  tz = cx*nz - sx*ny
  tx(w,1) = tx*400/ tz
  ty(w,1) = ty*400/ tz
  tz(w,1) = tz
  pz = m/2-posz
  nz = cy*pz + sy*nx
  tx = cy*nx - sy*pz
  ty = cx*ny + sx*nz
  tz = cx*nz - sx*ny
  tx(w,2) = tx*400/ tz
  ty(w,2) = ty*400/ tz
  tz(w,2) = tz
  px = ix2(w)*m-posx
  py = iy2(w)*m-posy
  pz = m/2-posz
  nx = cz*px + sz*py
  ny = cz*py - sz*px
  nz = cy*pz + sy*nx
  tx = cy*nx - sy*pz
  ty = cx*ny + sx*nz
  tz = cx*nz - sx*ny
  tx(w,3) = tx*400/ tz
  ty(w,3) = ty*400/ tz
  tz(w,3) = tz
  pz =-m/2-posz
  nz = cy*pz + sy*nx
  tx = cy*nx - sy*pz
  ty = cx*ny + sx*nz
  tz = cx*nz - sx*ny
  tx(w,4) = tx*400/ tz
  ty(w,4) = ty*400/ tz
  tz(w,4) = tz
 next
end sub

sub cast_rays()
 leftz = rotz(0) - 32 : if (leftz < 000) leftz = leftz + 255
 rigtz = rotz(0) + 32 : if (rigtz > 255) rigtz = rigtz - 255
 posx = posx(0)
 posy = posy(0)
 cs_lz = cs(leftz)
 sn_lz = sn(leftz)
 cs_rz = cs(rigtz)
 sn_rz = sn(rigtz)
 cslz = cs(leftz) + posx
 snlz = sn(leftz) + posy
 csrz = cs(rigtz) + posx
 snrz = sn(rigtz) + posy
 for w = 1 to walls
  cp1(w) = 0
  cp1 = (posx-wx1(w))*(snlz-wy1(w)) - (cslz-wx1(w))*(posy-wy1(w))
  if (cp1 > 0) then
   cp2 = (posx-wx1(w))*(snrz-wy1(w)) - (csrz-wx1(w))*(posy-wy1(w))
   if (cp2 < 0) then
    cp1(w) = 1
    ix1(w) = wx1(w)
    iy1(w) = wy1(w)
   fi
  fi
  cp2(w) = 0
  cp1 = (posx-wx2(w))*(snlz-wy2(w)) - (cslz-wx2(w))*(posy-wy2(w))
  if (cp1 > 0) then
   cp2 = (posx-wx2(w))*(snrz-wy2(w)) - (csrz-wx2(w))*(posy-wy2(w))
   if (cp2 < 0) then
    cp2(w) = 1
    ix2(w) = wx2(w)
    iy2(w) = wy2(w)
   fi
  fi

  if (cp1(w) = 0) then
   if    (wx1(w) = wx2(w)) then
    opp = wx1(w) - posx
    adj = opp/cs_lz*sn_lz + posy
    if    (adj > wy1(w)) and (adj < wy2(w)) then
     ix1(w) = wx1(w)
     iy1(w) = adj
    elsif (adj < wy1(w)) and (adj > wy2(w)) then
     ix1(w) = wx1(w)
     iy1(w) = adj
    fi
   elsif (wy1(w) = wy2(w)) then
    adj = wy1(w) - posy
    opp = adj/sn_lz*cs_lz + posx
    if    (opp > wx1(w)) and (opp < wx2(w)) then
     ix1(w) = opp
     iy1(w) = wy1(w)
    elsif (opp < wx1(w)) and (opp > wx2(w)) then
     ix1(w) = opp
     iy1(w) = wy1(w)
    fi
   fi
  fi
  if (cp2(w) = 0) then
   if    (wx1(w) = wx2(w)) then
    opp = wx2(w) - posx
    adj = opp/cs_rz*sn_rz + posy
    if    (adj > wy1(w)) and (adj < wy2(w)) then
     ix2(w) = wx2(w)
     iy2(w) = adj
    elsif (adj < wy1(w)) and (adj > wy2(w)) then
     ix2(w) = wx2(w)
     iy2(w) = adj
    fi
   elsif (wy1(w) = wy2(w)) then
    adj = wy2(w) - posy
    opp = adj/sn_rz*cs_rz + posx
    if    (opp > wx1(w)) and (opp < wx2(w)) then
     ix2(w) = opp
     iy2(w) = wy2(w)
    elsif (opp < wx1(w)) and (opp > wx2(w)) then
     ix2(w) = opp
     iy2(w) = wy2(w)
    fi
   fi
  fi
  for l = 1 to light
   opp = ix1(w)-lx(l)
   adj = iy1(w)-ly(l)
   hyp1 = sqrt(sqr(opp)+sqr(adj))/lit(l)
   lt1(w) = 1/hyp1 + lt1(w)
   opp = ix2(w)-lx(l)
   adj = iy2(w)-ly(l)
   hyp2 = sqrt(sqr(opp)+sqr(adj))/lit(l)
   lt2(w) = 1/hyp2 + lt2(w)
  next
  lt1(w) = lt1(w) / 4
  lt2(w) = lt2(w) / 4
  if (lt1(w) > 1) lt1(w) = 1
  if (lt2(w) > 1) lt2(w) = 1
  ? lt1(w),lt2(w)
 next
 ?
end sub

sub ctrl_user(ctrl) local dirx, diry, torx, torz, newx, newy
 if    (and(ctrl, ctrl(cr)) <> 0) then torz = 10*rpm
 elsif (and(ctrl, ctrl(sq)) <> 0) then torz =-10*rpm
 fi
 if    (and(ctrl, ctrl(tr)) <> 0) then torx = 10*rpm
 elsif (and(ctrl, ctrl(ex)) <> 0) then torx =-10*rpm
 fi
 rotz(0) = rotz(0) + torz
 if    (rotz(0) < 000) then rotz(0) = rotz(0) + 255
 elsif (rotz(0) > 255) then rotz(0) = rotz(0) - 255
 fi
 rotx(0) = rotx(0) + torx
 if    (rotx(0) > 128) then rotx(0) = 128
 elsif (rotx(0) < 000) then rotx(0) = 000
 fi

 if    (and(ctrl, ctrl(up)) <> 0) then
  dirx = cs(rotz(0))
  diry = sn(rotz(0))
 elsif (and(ctrl, ctrl(dn)) <> 0) then
  dirx =-cs(rotz(0))
  diry =-sn(rotz(0))
 fi
 if    (and(ctrl, ctrl(rt)) <> 0) then
  dirx = ct(rotz(0)) + dirx
  diry = tn(rotz(0)) + diry
 elsif (and(ctrl, ctrl(lf)) <> 0) then
  dirx =-ct(rotz(0)) + dirx
  diry =-tn(rotz(0)) + diry
 fi
 dirx = dirx*mps/4
 diry = diry*mps/4
 newx = posx(0) + dirx
 newy = posy(0) + diry
 hit = grid(newx, newy)
 if    (hit = door) then
  source = grid
  grid = des(node(newx, newy))
  load_grid(grid)
  newx = posx(0)
  newy = posy(0)
 elsif (hit <> flor) then
  newx = posx(0)
  newy = posy(0)
 fi
 posx(0) = newx
 posy(0) = newy
 cast_rays()
 rota_grid()
end sub

sub load_grid(grid) local x, y, w, g
 find_grid(grid)
 read gridx, gridy
 redim grid(gridx, gridy), node(gridx, gridy)
 for y = 1 to gridy read g
  for x = 0 to gridx grid(x, y) = 0 : node(x, y) = 0
   if (and(g, ctrl(x)) <> 0) grid(x, y) = wall
  next
 next
 read doors : if (doors <> 0) load_door(doors)
 read light : if (light <> 0) load_ligt(light)
 read bots : if (bots <> 0) load_bots(bots)
 for d = 0 to doors
  if (des(d) = source) then
   posx = dropx(d)
   posy = dropy(d)
  fi
 next
 posx(0) = posx + 0.5
 posy(0) = posy + 0.5
 read walls
 redim wx1(walls), wy1(walls), wx2(walls), wy2(walls)
 redim ix1(walls), iy1(walls), ix2(walls), iy2(walls)
 redim red(walls), grn(walls), blu(walls)
 redim lt1(walls), lt2(walls)
 redim cp1(walls), cp2(walls)
 redim tx(walls,4), ty(walls,4), tz(walls,4)
 for w = 1 to walls read wx1(w), wy1(w), wx2(w), wy2(w) next
 for w = 1 to walls read red(w), grn(w), blu(w) next
end sub

sub load_bots(bots)
end sub

sub load_door(doors) redim des(doors), dropx(doors), dropy(doors)
 for d = 1 to doors read dx, dy, dropx(d), dropy(d), des(d)
  grid(dx, dy) = door
  node(dx, dy) = d
 next
end sub

sub load_ligt(light)
 redim lx(light), ly(light), lit(light)
 for l = 1 to light read lx(l), ly(l), lit(l) next
end sub

sub find_grid(grid) on grid goto 01,02,03,04
01 restore grid_01 : return
02 restore grid_02 : return
03 restore grid_03 : return
04 restore grid_04 : return
end sub

sub init_game() local p, n, d, deg, degree
 m = 10
 km = 1000*m
 secs = 50
 mins = 60*secs
 hour = 60*mins
 mps = m/secs
 kph = km/hour
 rpm = 255/mins
 degree = pi / 128
 dim cs(255), sn(255), tn(255), ct(255)
 for d = 0 to 255 deg = d*degree
  cs(d) = cos(deg)
  sn(d) = sin(deg)
  ct(d) = cos(deg+pi/2)
  tn(d) = sin(deg+pi/2)
 next
 dim ctrl(16)
 n = 1
 for p = 1 to 16 ctrl(p) = n : n = n*2 next
 up = 05
 rt = 06
 dn = 07
 lf = 08
 tr = 13
 cr = 14
 ex = 15
 sq = 16
 flor = 0
 wall = 1
 door = 2
 redim posx(1), posy(1), posz(1)
 redim rotx(1), roty(1), rotz(1)
 redim dropx(1), dropy(1)
 dropx(0) = 8
 dropy(0) = 8
 grid = 01
 load_grid(grid)
 open window 640,512
 window origin "cc"
 intro = 0
 count = 0
 display = 8*secs
 dim message$(3)
 message$(0) = "Don't be afraid. Stick your chin up ..."
 message$(1) = "Press [Triangle] to look up"
 message$(2) = "Now step foward and claim your destiny ..."
 message$(3) = "Press [D-Pad] to move around"
end sub

label grid_01
data 16,16
data 65535,32769,32769,32769,32769,32769,32769,32769
data 32769,32769,32769,32769,32769,32769,32769,65535
data 1
data 16,08,15,08,02
data 4
data 0.5,0.5,1.5, 16.5,0.5,1.5, 16.5,16.5,1.5, 0.5,16.5,1.5
data 0
data 9
data 01,01,08,01, 08,01,17,01, 17,01,17,08, 17,08,17,09
data 17,09,17,17, 17,17,08,17, 08,17,01,17, 01,17,01,08
data 01,08,01,01
data 255,255,255, 255,255,255, 255,255,255, 150,120,080
data 255,255,255, 255,255,255, 255,255,255, 255,255,255
data 255,255,255

label grid_02
data 16,16
data 65535,32769,32769,32769,32769,32769,32769,32769
data 32769,32769,32769,32769,32769,32769,32769,65535
data 2
data 01,08,02,08,01, 16,08,15,08,03
data 4
data 8.5,0.5,1.5, 16.5,8.5,1.5, 8.0,16.5,1.5, 0.5,8.5,1.5
data 0
data 10
data 01,01,08,01, 08,01,17,01, 17,01,17,08, 17,08,17,09
data 17,09,17,17, 17,17,08,17, 08,17,01,17, 01,17,01,09
data 01,09,01,08, 01,08,01,01
data 255,255,255, 255,255,255, 255,255,255, 150,120,080
data 255,255,255, 255,255,255, 255,255,255, 255,255,255
data 150,120,080, 255,255,255

label grid_03
data 16,16
data 65535,32769,32769,32769,32769,32769,32769,32769
data 32769,32769,32769,32769,32769,32769,32769,65535
data 2
data 01,08,02,08,02, 16,08,15,08,04
data 4
data 0.5,0.5,1.5, 16.5,0.5,1.5, 16.5,16.5,1.5, 0.5,16.5,1.5
data 0
data 10
data 01,01,08,01, 08,01,17,01, 17,01,17,08, 17,08,17,09
data 17,09,17,17, 17,17,08,17, 08,17,01,17, 01,17,01,09
data 01,09,01,08, 01,08,01,01
data 255,255,255, 255,255,255, 255,255,255, 150,120,080
data 255,255,255, 255,255,255, 255,255,255, 255,255,255
data 150,120,080, 255,255,255

label grid_04
data 16,16
data 65535,32769,32769,32769,32769,32769,32769,32769
data 32769,32769,32769,32769,32769,32769,32769,65535
data 1
data 01,08,02,08,03
data 4
data 8.5,0.5,1.5, 16.5,8.5,1.5, 8.0,16.5,1.5, 0.5,8.5,1.5
data 0
data 9
data 01,01,08,01, 08,01,17,01, 17,01,17,08, 17,08,17,17
data 17,17,08,17, 08,17,01,17, 01,17,01,09, 01,09,01,08
data 01,08,01,01
data 255,255,255, 255,255,255, 255,255,255, 255,255,255
data 255,255,255, 255,255,255, 255,255,255, 150,120,080
data 255,255,255
 

Challenge Trophies Won:

Offline Jim

  • Founder Member
  • DBF Aficionado
  • ********
  • Posts: 5301
  • Karma: 402
    • View Profile
Re: Real Time 3D Interiors
« Reply #1 on: December 29, 2006 »
Amazing what you can do in yabasic!  What about adding some other things into the maze?

Jim
Challenge Trophies Won:

Offline Stonemonkey

  • Pentium
  • *****
  • Posts: 1315
  • Karma: 96
    • View Profile
Re: Real Time 3D Interiors
« Reply #2 on: December 29, 2006 »
Very nice, are you doing this on the ps2 too?

Offline rain_storm

  • Here comes the Rain
  • DBF Aficionado
  • ******
  • Posts: 3088
  • Karma: 182
  • Rain never hurt nobody
    • View Profile
    • org_100h
Re: Real Time 3D Interiors
« Reply #3 on: December 29, 2006 »
I think my PS2 days will be over just as soon as I have finished transferring the code from my memory card to my PC. (The emulator lets you speed up your code by syncing to the monitors refresh rate, THAT ROCKS BABY!!!). So yes in the past I coded exclusively on the PS2.
As for which direction this little project will go I am undecided. Either a 3D shooter or an action RPG (Like Vagrant Story). But first I want to clean up the code I hate messy spegetti code. And the above code has too many cheap fixes that I'm simply not happy with. Once I have everything optimised then I will get down to turning this engine into a game.

Challenge Trophies Won:

Offline Shockwave

  • good/evil
  • Founder Member
  • DBF Aficionado
  • ********
  • Posts: 17412
  • Karma: 498
  • evil/good
    • View Profile
    • My Homepage
Re: Real Time 3D Interiors
« Reply #4 on: December 30, 2006 »
I was very surprised when I looked up :) That's really nice work, it would be great to see the square room turned into a more complicated structure, I like it a lot though, well done.  :clap:
Shockwave ^ Codigos
Challenge Trophies Won:

Offline rain_storm

  • Here comes the Rain
  • DBF Aficionado
  • ******
  • Posts: 3088
  • Karma: 182
  • Rain never hurt nobody
    • View Profile
    • org_100h
Re: Real Time 3D Interiors
« Reply #5 on: December 30, 2006 »
I'm one step ahead of you Shockwave, I am currently including NPCs which have a field of view (Which Im borrowing from Clankys Unresolved Client) at the moment they are simply positions and are not animated. I would love to use reverse kinematics (Where rotations of the child bones effect their parent bone acting more like a cars suspension) for the animation but it is very complicated so I think I'll end up sticking with the traditional foward kinematics (Where the rotations of the parent bone is added to all child bones) I have increased the complexity of the rooms and should have a working update in the near futer. I hope I have enough processing power left to animate the players charictor so that the game can be played in 3rd person view. Anyhow once the animated NPC are working I'll post an update.

Challenge Trophies Won:

Offline Shockwave

  • good/evil
  • Founder Member
  • DBF Aficionado
  • ********
  • Posts: 17412
  • Karma: 498
  • evil/good
    • View Profile
    • My Homepage
Re: Real Time 3D Interiors
« Reply #6 on: December 30, 2006 »
You know what, how about an emulator only version? That would be excellent :) You could put loads of stuff into it.
Shockwave ^ Codigos
Challenge Trophies Won:

Offline rain_storm

  • Here comes the Rain
  • DBF Aficionado
  • ******
  • Posts: 3088
  • Karma: 182
  • Rain never hurt nobody
    • View Profile
    • org_100h
Re: Real Time 3D Interiors
« Reply #7 on: December 31, 2006 »
What does emulator only mean are thier commands that only apply to the emulator? Or is it simply a case using a layout of buttons that is intended for use with a keyboard rather than a controller?

Challenge Trophies Won:

Offline Jim

  • Founder Member
  • DBF Aficionado
  • ********
  • Posts: 5301
  • Karma: 402
    • View Profile
Re: Real Time 3D Interiors
« Reply #8 on: December 31, 2006 »
It's just massively faster than a PS2, so you can put more in.

Jim
Challenge Trophies Won:

Offline Clanky

  • Laser Guided Memories
  • Amiga 1200
  • ****
  • Posts: 340
  • Karma: 16
  • kiss that sound that pounds your senses
    • View Profile
Re: Real Time 3D Interiors
« Reply #9 on: January 01, 2007 »
All the emulator does is pass your program from YaBASIC into a language which the computer can understand... this allows the computer to read the YaBASIC commands, all the functionalities of the PS2 version are there - so use the same commands, values for controls, etc.
It's YaBASIC: for PC!
Also, as Jim already stated, it's alot faster - normally runs at your computers speed, compared with the 200 MHz PS2 processor.

(I THINK???)
He tilts, and his eyes are focused on the ground far below.. Wind? Angels? Men..

Offline rain_storm

  • Here comes the Rain
  • DBF Aficionado
  • ******
  • Posts: 3088
  • Karma: 182
  • Rain never hurt nobody
    • View Profile
    • org_100h
Re: Real Time 3D Interiors
« Reply #10 on: January 07, 2007 »
Okay I discovered a flaw in the program with regards to the order in which objects should be drawn relative to the room. I have sorted it out now. But fixing this has taken up some valueable time that should have been spent on getting the animation up and running. Anyhow no use in beatin' a dead horse. I'm gonna get the animation done asap. This project is gonna take alot of time. There is an updated version but I would rather have this part done before I post it.

Edit -
Alas I had to abandon this project! The code has become so bug-ridden that it was more feasible to start again from scratch. Also I had literally no more speed left for adding in bullets and so on. I could have optimised stuff but the bugs scared me off of this daunting task.

But not to fear as I have decided to go 100% raycaster on the mutha #@(k3r. The change has allowed me to texture map the rooms surfaces and      the boost in speed is enormous. Speed can be further increased simply by casting fewer rays! Of course things will look a little blockier. Anyway check it out for yourself in my latest topic ... Yabasic Rocks !!!
« Last Edit: January 09, 2007 by rain_storm »

Challenge Trophies Won: