"Looking" at a 3D model

Hey All,

I am working on some 3D stuff for a visualization class. I am hitting a slight road block, however, when it comes to “looking” at the 3D model I have made. I’ve tried a couple of things with matrix transforms but to no avail. Can any of you give some advice on how to get my model on the screen?

Hi @blmacbeth

If you look at the source of the 3D Lab example that comes with Codea, you’ll notice the following:

perpective(fov) and camera(eyeX, eyeY, eyeZ, lookAtX, lookAtY, lookAtZ, upX, upY, upZ).

fov = Field of View, a “standard” value is 60

eyeXYZ is the eye vector (wherever you want your camera to be)

lookAtXYZ where it looks at (so 0, 0, 0 is you’re looking at the center)

and upXYZ the up vector (usually Y or Z up, so 0, 1, 0 or 0, 0, 1)

That’s basically all you need :slight_smile:

Cheers

I’d just like to add that you’ll also want to use either parameter or iparameter sliders for the fov.
also

translate(x,y,z)
rotate(Angle,0,1,0)

Here’s a small example that might help.


function setup()
    iparameter("R",-360,360, 60)
    parameter("x",0,1,.5)
    parameter("y",0,1,.5)
    parameter("z",0,1,.5)
    iparameter("size", 1, 50, 20)
end

function draw()
    background(0, 0, 0, 255)
    perspective(50,WIDTH/HEIGHT)
    camera(-200,0,0,0,0,0,0,1,0)
    rotate(R,x,y,z)
    fill(255, 0, 0, 255)
    cube(0,0,0,size,size,size)
end

function cube(x,y,z,w,h,d)
    local cube = mesh()
    v = { 
        vec3(x-w,y-h,z+d),vec3(x-w,y+h,z+d),vec3(x+w,y-h,z+d),vec3(x+w,y+h,z+d),
        vec3(x-w,y-h,z-d),vec3(x-w,y+h,z-d),vec3(x+w,y-h,z-d),vec3(x+w,y+h,z-d)
       }
    
    local faces = {
        v[1],v[2],v[3],v[2],v[3],v[4],
        v[2],v[4],v[6],v[4],v[6],v[8],
        v[1],v[2],v[5],v[2],v[5],v[6],
        v[3],v[4],v[7],v[4],v[7],v[8],
        v[1],v[3],v[5],v[3],v[5],v[7],
        v[5],v[6],v[7],v[6],v[7],v[8]
    }
    local c = { color(255, 0, 0, 255), color(0, 255, 0, 255), color(255, 243, 0, 255),
        color(0, 0, 255, 255), color(255, 255, 255, 255), color(255, 0, 189, 255)}
    local colors = {}
    for i = 1, 6 do
        for j = 1, 6 do
        table.insert(colors, c[i])
        end
    end
    cube.vertices = faces
    cube.colors = colors
    cube:draw()
end

Alrighty. I have proven that I can view something in 3D. However, I cannot make a 3D object. Here is my code to make a 3D graphed for a visualization program I am working on. What am I doing wrong? The vectors in the main class are my tests and what not. That mesh is drawn in the graphed classes draw function as I was too lazy to copy and paste the matrices to the main (it also felt redundant).


-- 3D Grapher

-- Use this function to perform your initial setup
function setup()
    print("Hello World!")
    
    iparameter("R",-360,360, 60)
    parameter("x",0,1,.5)
    parameter("y",0,1,.5)
    parameter("z",0,1,.5)
    parameter("cam",-300,0,-200)
    iparameter("size", 1, 50, 20)
    
    graph = Grapher3D(myFunction)
    ms = mesh()
    ms.vertices = {vec3(0,0,myFunction(0,0)),
                   vec3(1,0,myFunction(1,0)),
                   vec3(1,1,myFunction(1,1)),
                
                   vec3(0,0,myFunction(0,0)),
                   vec3(1,1,myFunction(1,1)),
                   vec3(0,1,myFunction(0,1)),
                
                   vec3(0,0,myFunction(0,0)),
                   vec3(-1,0,myFunction(-1,0)),
                   vec3(-1,-1,myFunction(-1,-1)),
                
                   vec3(0,0,myFunction(0,0)),
                   vec3(-1,-1,myFunction(-1,-1)),
                   vec3(0,-1,myFunction(0,-1))}
    ms:setColors(127,127,127,255)
end

function myFunction(x,y)
    return x*x-y*y
end

-- This function gets called once every frame
function draw()
    -- This sets a dark background color 
    background(40, 40, 50)

    -- This sets the line thickness
    strokeWidth(5)

    -- Do your drawing here
    graph:draw()
end

Grapher3D class


Grapher3D = class()

function Grapher3D:init(f)
    -- you can accept and set parameters here
    self.min_x = -10
    self.max_x = 10
    self.min_y = -10
    self.max_y = 10
    self.m = mesh()
    
    print(f(2,3))
   
    for x = self.min_x, self.max_x do
        for y = self.min_y, self.max_y do
            -- Box around the point going from current point to the next
                                             -- First Triangle
                                            
            vecs = {vec3(x,  y,  f(x,  y)),  -- current point
                    vec3(x+1,y,  f(x+1,y)),  -- next x coord
                    vec3(x+1,y+1,f(x+1,y+1)),-- next point
                    
                                             -- Second Triangle
                                            
                    vec3(x,  y,  f(x,  y)),  -- current point
                    vec3(x+1,y+1,f(x+1,y+1)),-- next point
                    vec3(x,  y+1,f(x,  y+1))}-- next y coord
            for i = 1, #vecs do
                table.insert(self.m.vertices, vecs[i])
            end
        end
    end
    self.m:setColors(127,127,127,255)
end

function Grapher3D:draw()
    -- Codea does not automatically call this method
    pushMatrix()
    perspective(50,WIDTH/HEIGHT)
    camera(cam,0,0,0,0,0,0,1,0)
    rotate(R,x,y,z)
    scale(size)
    self.m:draw()
    ms:draw()
    popMatrix()
end

function Grapher3D:touched(touch)
    -- Codea does not automatically call this method
end

I finally fixed the code and it works great! I added some stuff to control how it breaks up the graph, etc. you’ll see.

Grapher3D = class()

function Grapher3D:init(f)
    -- you can accept and set parameters here
    self.f = f
    self.min_x = -10
    self.max_x = 10
    self.min_y = -10
    self.max_y = 10
    self.m = mesh()
    self.m.vertices = {}
    self:makeGraph()
end

function Grapher3D:makeGraph()
    local f = self.f
    local n = 0 -- the number of vertices in the mesh
    local vertices = {}
    n_x = 30 -- number of sections on x-axis
    n_y = 30 -- number of sections on y-axis
    dx = (self.max_x - self.min_x)/n_x
    dy = (self.max_y - self.min_y)/n_y
    for x = self.min_x, self.max_x, dx do
        for y = self.min_y, self.max_y, dx do
            -- Box around the point going from current point to the next
                                                  -- First Triangle
            
            vecs = {vec3(x,   y,   f(x,  y)),     -- current point
                    vec3(x+dx,y,   f(x+dx,y)),    -- next x coord
                    vec3(x+dx,y+dy,f(x+dx,y+dy)), -- next point
                    
                                                  -- Second Triangle
                                            
                    vec3(x,   y,   f(x,y)),       -- current point
                    vec3(x+dx,y+dy,f(x+dx,y+dy)), -- next point
                    vec3(x,   y+dy,f(x,y+dy))}    -- next y coord

            for i = 1, 6 do
                vertices[n+i] = vecs[i]
            end
            n = n + 6
        end
    end
    self.m.vertices = vertices
    print(vertices[2], x,y)
    self.m:setColors(127,127,127,255)
end

function Grapher3D:draw()
    -- Codea does not automatically call this method
    pushMatrix()
    perspective(FOV,WIDTH/HEIGHT)
    camera(cam,0,0,0,0,0,0,1,0)
    rotate(R,x,y,z)
    scale(size)
    self.m:draw()
    ms:draw()
    popMatrix()
end

function Grapher3D:touched(touch)
    -- Codea does not automatically call this method
end

Still needs lighting…