Howdy, Stranger!

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

Rendering three/four camera views on a single screen?

edited September 2012 in Questions Posts: 666

Does anyone recall 'Imagine' on the PC? Or any modern 3D editor? Three screens of 2D top, left, side and a 3d view of the model. I'd like to create that, but I can't seem to figure out how to render more than one camera.

I thought that I could setContext() and render to an image, then composite, but I can't seem to get a 3D viewport onto an image. I haven't even tried the 2d part yet...

Ideas? Thoughts? Help?

Comments

  • Posts: 2,161

    Render your scene three times and change the matrix in between each rendering.

  • Won't sure how that will be composited...I'm sure I can google up how to render the scene and change the matrix...the compositing of the 3d output wasn't working for me.

  • Is there a function in codea comparable to OpenGL viewport() to limit the drawing to a part of the screen? Because without that, how is it possible to draw on 1/4 th of the screen by just changing the matrix?

  • Right...hence the idea of drawing o a bitmap and compositing. Probably slow, but could work. I'm going to try to render a 3D view onto a bitmap...

  • Posts: 115

    Ah, the good old days on the Amiga. I still have TurboSilver and Imagine on floppy disks in my storage room along with an Amiga 1200. I gave away my Amiga 500 many moons ago. Never tried on a PC though.

    Good idea for a similar interface.

  • Unfortunately, setContext() does not capture the 3D eye, or more specifically, mesh draws are not redirected based on camera eye and context.

  • Posts: 2,161

    Just use clip to limit the viewport. That's unaffected by the current matrix.

  • Clipping is a good idea. But you have to take care of the center of your scene then to move it in the right quarter before rendering.

  • Posts: 2,161

    Here's a prototype for you. I'm not convinced that I have the touch handing quite right, but it moves it roughly in the right direction. Of course, to do it properly one would put everything in a viewport class.

    function setup()
        m = mesh()
        ver = {
            vec3(1,0,0),
            vec3(0,1,0),
            vec3(0,0,1),
            vec3(-1,0,0),
            vec3(0,1,0),
            vec3(0,0,1),
            vec3(1,0,0),
            vec3(0,-1,0),
            vec3(0,0,1),
            vec3(-1,0,0),
            vec3(0,-1,0),
            vec3(0,0,1),
            vec3(1,0,0),
            vec3(0,1,0),
            vec3(0,0,-1),
            vec3(-1,0,0),
            vec3(0,1,0),
            vec3(0,0,-1),
            vec3(1,0,0),
            vec3(0,-1,0),
            vec3(0,0,-1),
            vec3(-1,0,0),
            vec3(0,-1,0),
            vec3(0,0,-1)
        }
        c = {}
        vv = {}
        for k,v in ipairs(ver) do
            table.insert(c,color(128+v.x*127,128+v.y*127,128+v.z*127,255))
            table.insert(vv,v)
        end
        
        m.vertices = vv
        m.colors = c
        
        parameter("azimuth",0,2*math.pi,math.pi)
        parameter("zenith",0,math.pi,0)
        parameter("size",.1,5,1)
        dx,dy,dz = 0,0,0
    end
    
    function draw()
        background(40, 40, 50)
        clip(0,HEIGHT/2,WIDTH,HEIGHT)
        camera(0,0,10,0,0,0,0,1,0)
        drawObj(vec3(0,2,0))
        clip(0,0,WIDTH,HEIGHT/2)
        camera(0,10,10,0,0,0,1,0,0)
        drawObj(vec3(-2,0,0))
    end
        
    function drawObj(o)
        perspective(45,WIDTH/HEIGHT)
        
        local ca = math.cos(azimuth)
        local sa = math.sin(azimuth)
        local cz = math.cos(zenith)
        local sz = math.sin(zenith)
        local mt = 
            matrix(
            size,0,0,0,
            0,size,0,0,
            0,0,size,0,
            0,0,0,1        
            )*
            matrix(
            ca,-sa,0,0,
            sa,ca,0,0,
            0,0,1,0,
            0,0,0,1
            ) * matrix(
            1,0,0,0,
            0,cz,-sz,0,
            0,sz,cz,0,
            0,0,0,1
            ) * 
            GravityToMatrix() *
            matrix(
            1,0,0,0,
            0,1,0,0,
            0,0,1,0,
            o.x+dx,o.y+dy,o.z+dz,1
            )
            
            local j,k,l
        for i = 0,7 do
            j = 2*(i%2)-1
            k = 2*(math.floor(i/2)%2)-1
            l = 2*(math.floor(i/4)%2)-1
        modelMatrix(
            matrix(
            1,0,0,0,
            0,1,0,0,
            0,0,1,0,
            j,k,l,1
            ) *
            mt
        )
        m:draw()
        end
    end
    
    function touched(touch)
        if touch.y > HEIGHT/2 then
            dx = dx + 2*touch.deltaX/WIDTH
            dy = dy + 2*touch.deltaY/HEIGHT
        else
            dx = dx + 2*touch.deltaY/WIDTH
            dy = dy - 2*touch.deltaX/HEIGHT
        end
    end
    
    function GravityToMatrix()
        local gxy, gy, gygxy, a, b, c, d
        if Gravity.x == 0 and Gravity.y == 0 then
            a,b,c,d = 1,0,0,0
        else
            gy = - Gravity.y
            gxy = math.sqrt(math.pow(Gravity.x,2) + math.pow(Gravity.y,2))
            gygxy = gy/gxy
            a = math.sqrt(1 + gxy - gygxy - gy)/2
            b = math.sqrt(1 - gxy - gygxy + gy)/2
            c = math.sqrt(1 - gxy + gygxy - gy)/2
            d = math.sqrt(1 + gxy + gygxy + gy)/2
            if Gravity.y > 0 then
                    a = a
                    b = b
            end
            if Gravity.z < 0 then
                    b = - b
                    c = - c
            end
            if Gravity.x > 0 then
                    c = - c
                    d = - d
            end
        end
        a,b,c,d = a,d,-c,-b
        local aa = 2*a*a
        local ab = 2*a*b
        local ac = 2*a*c
        local ad = 2*a*d
        local bb = 2*b*b
        local bc = 2*b*c
        local bd = 2*b*d
        local cc = 2*c*c
        local cd = 2*c*d
        return matrix(
            1 - bb - cc,
            ab - cd,
            ac + bd,
            0,
            ab + cd,
            1 - aa - cc,
            bc - ad,
            0,
            ac - bd,
            bc + ad,
            1 - aa - bb,
            0,
            0,0,0,1
        )
    end
    
    
    
  • Ok, that's AMAZING! I didn't think you could have one camera, and then another camera… All in the same draw call, rendering different views! I removed the clip, and then I was even more amazed!

    I guess I was stuck in the paradigm of the physical world, where I expected one camera to move around and cause only one draw on the screen.

    I see the value of the clip. But I didn't expect the camera calls to do it to do what they did!

    Yes, your touch function was off. Adding the gravity Feature was value above the touch.

    Thanks so much for this example!

  • Posts: 2,161

    Yes, your touch function was off.

    Well, I had to leave something for others to figure out!

    Re Gravity: Partly this was some code I had left over from some experiments with meshes and matrices, which was what made it easy to adapt for this, and partly I really like the idea of using the fact that you can pick up and move an iPad to interact with it.

  • I's viewport a class or primitive function? I,m searching for it...

  • Posts: 2,161

    Neither! What I meant was that you would want to define a viewport class. Something like:

    Viewport = class()
    
    Viewport:init(t)
        t = t or {}
        self.centre = t.centre -- where I'm looking at
        self.eye = t.eye -- where I'm looking from
        self.up = t.up -- which way is up?
        self.bl = t.bottomLeft -- bottom left corner of region on screen
        self.tr = t.topRight -- top right corner of region on screen
    end
    
    Viewport:invoke(object)
        clip(self.bl.x,self.bl,y,self.tr.x,self.tr.y)
        camera(self.centre.x,self.centre.y,self.centre.z,<you get the idea>)
        -- some junk with matrices
        object:draw()
    end
    
    

    But it would need a bit of sitting down with a pen and paper (or finger and iPad) to work out the transformations. You'd also want to know how to transform a vector into and out of the viewport for transmitting, say, touch data.

  • Gotcha. I can use that to split my screen in quads. As far as translating touch, that's probably next week...when I figure out how to draw edges without faces...we don't have a wireframe mode!

  • Posts: 2,161

    Cheap wireframe is with a wireframe texture. But then you have issues with transparency in that what's underneath won't be drawn if it is drawn afterwards (so you can't make use of OpenGL's depth buffering, you have to do it yourself). Expensive way is to make a new mesh that is a wireframe version of the old one. With a load of auxiliary classes, it's not an unfeasible task.

  • I'm thinking that I'll rip through the mesh vertices and make the expensive version (later) I'm not relaly doing too well on my texture mapping; I can't seem to really get my head around the uv maps and vertices vs. faces (which I will need to understand later)

    The ehole point of this thing is to create something that can read X3D objects (already have that part done) as well as try to create very fundamental ones with the iPad. I'd like a simple "tree" with a few leaves and a brown trunk, for example, so that I can load a mesh and replicate it. I really don't like putting vertext code in LUA classes. The editor is tooooo slow for that, also.

  • Andrew, am i correctly interpreting the modelmatrix code to basically mean, "render 8 copies of this object"? Off of the same mesh?

  • Posts: 2,161

    Yes. It's a cheap way to get a slightly more complicated figure for my original experiments. That's what gave me the idea for the viewports for your code.

  • Interesting, because something like this could be used to create a large set of walls or a grid (which is what i started doing originally), i wrote a mesh merge function originally, but I'm likely to try to change it to the modelmatrix. Pretty neat.

  • @Andrew_Stacey - Thanks for the example, this just what I need to help get my head round the 3D stuff

  • edited January 2014 Posts: 666

    So...I was finally able to get a 3D scene to render in a Imagine/TurboSilver style with images and multiple cameras. However, for some reason, my object rendering seems to be out of order if I use SetContext(). If I render to the screen directly, the object renders fine.

    I know that I read something on the forums about the render engine...Update: the z-buffer bug...which was supposed to be fixed in 1.5...

  • @aciolino, do you see a similar issue to what I get from my code in http://twolivesleft.com/Codea/Talk/discussion/4322/detecting-touch-in-3d-issue#Item_29? When I draw to an image, it doesn't capture what I see on the screen.

  • IgnatzIgnatz Mod
    Posts: 5,396

    @aciolino - so that's what you've been working on for 15 months!

  • Posts: 2,161

    @aciolino setContext ignores z-buffering, is that what you're experiencing?

    (Related: https://bitbucket.org/TwoLivesLeft/core/issue/275/provide-option-to-turn-on-z-level. Simeon's said this shouldn't be too hard to implement, but maybe a few more people fussing about it would shift it up the priority list!)

  • edited January 2014 Posts: 666

    Yes, it's DEFINITELY a z-buffer issue.

    When I load a 3D object, I typically don't have control over the render order of the mesh :) so yes, it's pretty important :) Seeing that there was commentary from @Simeon that it was worked on after 1.4, I was curious if it was done or still in process.

    Screenshot of my Porsche model is here. https://www.dropbox.com/s/pa1580uqp174o4j/Bad 3D Rendering.png

  • Posts: 666

    @Ignatz - uh...yeah...that's right, it's been a long journey to get here! :) Actually I thought of a new way to approach this problem and wanted to try it out - it looked great until I realized that my cubes were rendering inverted, unless they had transparency, which was even MORE weird.

  • IgnatzIgnatz Mod
    Posts: 5,396

    @aciolino - an amazing coincidence, but I have just been wrestling with the identical problem where a cube made of four addRects draws perfectly normally unless you use setContext, then it is a mess.

    I resolved it by constantly sorting the sides to draw the furthest first, but there is a problem there.

Sign In or Register to comment.