This is a read-only snapshot of the ComputerCraft forums, taken in April 2020.
Gumball's profile picture

3D Effect

Started by Gumball, 12 December 2015 - 07:47 PM
Gumball #1
Posted 12 December 2015 - 08:47 PM
I'm creating a 3D Cube API, by that I mean it puts a texture into an easily rendered table, then it crops part of that table out to show a square at an "angle" then what it does is put a filter over the screen, where if the rotation is big, then the screen gets exponentially stretched, to add 3D effect. How would I go about the effect? The code is:


os.loadAPI("colorapi")

rotation = 0
length = 3

cube = {
  {
    "7777",
    "7777",
    "7777",
    "7777"
  },
  {
    "aaaa",
    "aaaa",
    "aaaa",
    "aaaa"
  },
  {
    "3333",
    "3333",
    "3333",
    "3333"
  },
  {
    "bbbb",
    "bbbb",
    "bbbb",
    "bbbb"
  }
}

function Pixel(str)
  for i=1,#str do
    term.setBackgroundColor(colorapi.codeToNum(str:sub(i,i)))
    write(" ")
  end
  write("\n")
end

function drawObject(sides,rotation,length)
  int = #sides
  draw = ""

  lines = {}

  for create=1,#sides[1] do
    lines[#lines + 1] = ""
  end

  --Pan effect... ??


  for a=1,int do
    side = sides[a]
    for b=1,#side do
	  lines[b] = lines[b]..sides[a][b]
    end
  end

  for i=1,#lines do
    term.setTextColor(colorapi.codeToNum(lines[i]:sub(i,i))) --ColorAPI aids with translating color codes, nothing special.
    Pixel(lines[i]:sub(rotation,rotation + length)) --Custom print function, just turns paint color codes into a colored pixel, pixel by pixel.
  end
  return lines
end

while true do
  local event, key = os.pullEvent("key")
    if(key == keys.right and rotation < 13) then
	  rotation = rotation + 1
	  term.setBackgroundColor(colors.black)
	  term.clear()
	  term.setCursorPos(1,1)
	  drawObject(cube,rotation,length)
    elseif(key == keys.left and rotation > 1) then
	  rotation = rotation - 1
	  term.setBackgroundColor(colors.black)
	  term.clear()
	  term.setCursorPos(1,1)
	  drawObject(cube,rotation,length)
    end
end
Bomb Bloke #2
Posted 13 December 2015 - 12:19 AM
I suggest you start out by defining your cube as a selection of points within a 3D grid, then figure out how to plot those onto your 2D screen.

Some trig is involved; the logic is described here. A brief summary is to think of yourself, the user of your computer, as being a part of the 3D space which your square inhabits; say you're at x0/y0/z0. Now think of your screen as being a flat plane within that space, say at z50 (covering x/y bounds equal to its resolution, perhaps scaled according to the field of view you want to achieve). Now calculate the angle between the points that make up your cube (which might be at about z500, say) and yourself; plot a line along that angle, and determine where it intersects the plane representing your screen. The x/y coords where it hits are the x/y coords where the point should be drawn on your actual display.

Once you've done that, it's simply a matter of filling in the polygons formed between those points using the colour of each side (this recent discussion may help you with that).

Things get a fair bit more complicated if you start using "patterned" textures (as opposed to just flat colours); I guess a ray cast would be the easiest way to do that within ComputerCraft (basically the same process in reverse). But that may be beyond your needs, and even if it isn't, I wouldn't worry about it until you've got a handle on the above.