Howdy, Stranger!

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

Pipe and Tunnel: experiments with meshes

edited August 2012 in Code Sharing Posts: 489

I have been experimenting with meshes with the following code, inspired by the Roller Coaster example project:


-- -- Pipe -- supportedOrientations(LANDSCAPE_ANY) function setup()     local randomColours = false -- True for different shading option     local pointNo = 30          -- No. of points in cross-section     local radius = 30           -- Cross-section radius     local path = Pipe.knot -- Choose path for pipe     parameter("r", 10, 1600, 1200)     parameter("theta", 0, 360, 0)     parameter("phi", 5, 175, 90) -- Avoid the discontinuity at poles     light = vec3(1, 0, 0) -- Direction to light source     ambient =0.25         -- Ambient light factor (0 to 1)     local c = rCol()      -- A random colour     local dt = 1/400      -- No of cross-sections in pipe     m = mesh()            -- Create a mesh     local ver = {}        -- Table for vertices     local col = {}        -- Table for their colours     for j = 0, 1 - dt, dt do -- For each cross-section in the pipe         p1 = circle(path(j),             tangent(dt, path, j), radius, pointNo)         p2 = circle(path(j+dt),             tangent(dt, path, j+dt), radius, pointNo)         for i = 1, pointNo do -- For each point in cross-section             local t1 = p1[i]             local t2 = p1[(i % pointNo)+1]             local t3 = p2[i]             local t4 = p2[(i % pointNo)+1]             table.insert(ver, t1) -- First triangle             table.insert(ver, t2)             table.insert(ver, t3)             table.insert(ver, t3) -- Second triangle             table.insert(ver, t2)                 table.insert(ver, t4)             local c1, c2             if not randomColours then                 local n1 = (t2 - t1):cross(t3 - t1)                 n1 = n1:normalize()                 local n2 = (t2 - t3):cross(t4 - t3)                 n2 = n2:normalize()                 local i1 = (math.max(n1:dot(light), 0) *                      (1 - ambient) + ambient)                 local i2 = (math.max(n2:dot(light), 0) *                      (1 - ambient) + ambient)                 c1 = color(c.r*i1, c.g*i1, c.b*i1)                 c2 = color(c.r*i1, c.g*i1, c.b*i1)             else                 c1 = rCol() -- A random colour                 c2 = rCol() -- Another random colour             end             table.insert(col, c1) -- First triangle             table.insert(col, c1)             table.insert(col, c1)             table.insert(col, c2) -- Second triangle             table.insert(col, c2)             table.insert(col, c2)         end     end     m.vertices = ver -- Set vertices     m.colors = col   -- Set their colours end function draw()     background(0)      local eye = eye(r, theta, phi) -- Get position of the eye     pushMatrix()     perspective() -- Set the default perspective     camera(eye.x, eye.y, eye.z, 0, 0, 0, 0, 1, 0) -- Set camera     m:draw()                                      -- Draw mesh     popMatrix() end Pipe = {} -- Function to define a path of the pipe function Pipe.rollerCoaster(t)     local a = t * 2 * math.pi     local r = 300      local y = r/2 * math.sin(3*a)     local x = r * math.cos(a)     local z = r * math.sin(2*a)     return vec3(x, y, z) end -- Function to define a path of the pipe function Pipe.knot(t)     local a = t * 2 * math.pi * 3     local r = 200 * (1 + math.cos(5 * a / 3))     local y = 100 * math.sin(5 * a / 3)     local x = r * math.cos(a)     local z = r * math.sin(a)     return vec3(x, y, z) end -- Function to estimate tangent of f(t) at t function tangent(delta, f, t)     local u = t - delta/2     local v = t + delta/2     local df = f(v) - f(u)     return df:normalize() end -- Function returns points of next cross-section local ov2 = nil function circle(origin, dir, radius, pointNo)     local points = {}     local v1 = dir:cross(ov2 or vec3(1, 0, 0))     local v2 = dir:cross(v1)     v1 = v1:normalize()     v2 = v2:normalize()     ov2 = -v2     for i = 0, pointNo - 1 do         local a = i/pointNo * 2 * math.pi         local p = origin +              (v1 * math.cos(a) + v2 * math.sin(a)) * radius         table.insert(points, p)     end     return points end -- Returns a random colour function rCol()     local red = math.random(255)     local green = math.random(255)     local blue = math.random(255)         return color(red, green, blue) end -- Returns position of eye function eye(r, thetaDeg, phiDeg)     local deg2rad = math.pi/180 -- Conversion factor     local theta = thetaDeg * deg2rad     local phi = phiDeg * deg2rad     local x = r * math.cos(theta)*math.sin(phi)     local z = r * math.sin(theta)*math.sin(phi)     local y = r * math.cos(phi)     return vec3(x, y, z) end
Tagged:

Comments

  • dave1707dave1707 Mod
    Posts: 8,624

    Nice example of meshes. I like how you can go thru a tube and look at it from the inside. Is there anyway you can change the eye x,y,z location and viewing direction to allow the illusion that you're moving along the inside of the tubes. It would be interesting to work your way along the inside of the tubes and see the inside of where they come together.

  • Posts: 489

    Hello @dave1707. Below is a variation - Tunnel - inspired by your suggestion. (Warning: this involves rapidly moving coloured elements.)

    --
    -- Tunnel
    --
    supportedOrientations(LANDSCAPE_ANY)
    displayMode(FULLSCREEN)
    function setup()
        local randomColours = true -- False for different shading option
        local pointNo = 30         -- No. of points in cross-section
        local radius = 30          -- Cross-section radius
        path = Pipe.rollerCoaster  -- Choose path for pipe
        speed = 1/20               -- Speed of animation
    
        light = vec3(1, 0, 0) -- Direction to light source
        ambient =0.25         -- Ambient light factor (0 to 1)
        local c = rCol()      -- A random colour
        dt = 1/400            -- No of cross-sections in pipe
        m = mesh()            -- Create a mesh
        local ver = {}        -- Table for vertices
        local col = {}        -- Table for their colours
        for j = 0, 1 - dt, dt do -- For each cross-section in the pipe
            p1 = circle(path(j),
                tangent(dt, path, j), radius, pointNo)
            p2 = circle(path(j+dt),
                tangent(dt, path, j+dt), radius, pointNo)
            for i = 1, pointNo do -- For each point in cross-section
                local t1 = p1[i]
                local t2 = p1[(i % pointNo)+1]
                local t3 = p2[i]
                local t4 = p2[(i % pointNo)+1]
                table.insert(ver, t1) -- First triangle
                table.insert(ver, t2)
                table.insert(ver, t3)
                table.insert(ver, t3) -- Second triangle
                table.insert(ver, t2)    
                table.insert(ver, t4)
                local c1, c2
                if not randomColours then
                    local n1 = (t2 - t1):cross(t3 - t1)
                    n1 = n1:normalize()
                    local n2 = (t2 - t3):cross(t4 - t3)
                    n2 = n2:normalize()
                    local i1 = (math.max(n1:dot(light), 0) * 
                        (1 - ambient) + ambient)
                    local i2 = (math.max(n2:dot(light), 0) * 
                        (1 - ambient) + ambient)
                    c1 = color(c.r*i1, c.g*i1, c.b*i1, 255)
                    c2 = color(c.r*i1, c.g*i1, c.b*i1, 255)
                else
                    c1 = rCol() -- A random colour
                    c2 = rCol() -- Another random colour
                end
                table.insert(col, c1) -- First triangle
                table.insert(col, c1)
                table.insert(col, c1)
                table.insert(col, c2) -- Second triangle
                table.insert(col, c2)
                table.insert(col, c2)
            end
        end
        m.vertices = ver -- Set vertices
        m.colors = col   -- Set their colours
    end
    
    function draw()
        t = ElapsedTime * speed
        background(0) 
        local eye = eye(t) -- Get position of the eye
        local dir = eye + tangent(dt, path, t)
        pushMatrix()
        perspective() -- Set the default perspective
        camera(eye.x, eye.y, eye.z, -- Set eye location
            dir.x, dir.y, dir.z,    -- Set direction of eye
            0, 1, 0)                -- Set orientation of eye
        m:draw()                    -- Draw mesh
        popMatrix()
    end
    
    Pipe = {}
    
    -- Function to define a path of the pipe
    function Pipe.rollerCoaster(t)
        local a = t * 2 * math.pi
        local r = 300 
        local y = r/2 * math.sin(3*a)
        local x = r * math.cos(a)
        local z = r * math.sin(2*a)
        return vec3(x, y, z)
    end
    
    -- Function to define a path of the pipe
    function Pipe.knot(t)
        local a = t * 2 * math.pi * 3
        local r = 200 * (1 + math.cos(5 * a / 3))
        local y = 100 * math.sin(5 * a / 3)
        local x = r * math.cos(a)
        local z = r * math.sin(a)
        return vec3(x, y, z)
    end
    
    -- Function to estimate tangent of f(t) at t
    function tangent(delta, f, t)
        local u = t - delta/2
        local v = t + delta/2
        local df = f(v) - f(u)
        return df:normalize()
    end
    
    -- Function returns points of next cross-section
    local ov2 = nil
    function circle(origin, dir, radius, pointNo)
        local points = {}
        local v1 = dir:cross(ov2 or vec3(1, 0, 0))
        local v2 = dir:cross(v1)
        v1 = v1:normalize()
        v2 = v2:normalize()
        ov2 = -v2
        for i = 0, pointNo - 1 do
            local a = i/pointNo * 2 * math.pi
            local p = origin + 
                (v1 * math.cos(a) + v2 * math.sin(a)) * radius
            table.insert(points, p)
        end
        return points
    end
    
    -- Returns a random colour
    function rCol()
        local red = math.random(255)
        local green = math.random(255)
        local blue = math.random(255)    
        return color(red, green, blue)
    end
    
    -- Returns position of eye
    function eye(t)
        return path(t)
    end
    
  • dave1707dave1707 Mod
    edited August 2012 Posts: 8,624

    @mpilgrem

    Fantastic. That's what I had in mind. It makes me dizzy just watching it. Another great example of using meshes. I can't tell, but are you following just one loop or is it going thru a different loop each time.

  • Posts: 2,161

    That's great. Very fluid motion.

    I put a half-tunnel track into the latest version of the roller coaster (so you can still see the stars).

  • SimeonSimeon Admin Mod
    Posts: 5,417

    Just posting a picture of your project, @mpilgrem, it's very good.

    Tunnel

  • edited August 2012 Posts: 154

    Wow

  • Posts: 489

    Thank you for your kind words. I should emphasise the debt that this code owes to the existence of @Andrew_Stacey's Roller Coaster example project, and to @dave1707's encouragement.

  • edited August 2012 Posts: 437

    I found quite interesting this prototype, i have changed the rCol() function to give a solid look to the tunnel, give it a try!!

    -- Returns a random colour
    red = math.random(255)
    green = math.random(255)
    blue = math.random(255)  
    function rCol()
        local r = math.random(1,3)
        if r == 2 then
            inc = -1
        elseif r == 3 then
            inc = 1
        else 
            inc = 0
        end
        if inc~=0 then 
            red = morecolor(red,inc)
            blue = morecolor(blue,inc)
            green = morecolor(green,inc)
        end
        return color(red, green, blue)
    end
    
    function morecolor(c,inc)
        c = c + inc
        if c>255 or c<0 then
            c = math.random(255)
        end
        return c
    end 
    
    

    :)

    Your skills with meshes blow my mind @mpilgrem

  • Posts: 179

    That is fairly awesome, @mpilgrem. And in less than 150 lines of code, impressive.

  • edited August 2012 Posts: 489

    Hello @juaxix. Did you mean the following (so that each circular 'segment' of the tunnel is, more a less, a single random colour)?

    -- Returns a random colour
    local red   = math.random(255)
    local green = math.random(255)
    local blue  = math.random(255)  
    function rCol()
        local inc = math.random(1, 3)
        if r == 2 then
            inc = -1
        elseif r == 3 then
            inc = 1
        else 
            inc = 0
        end
        if inc~=0 then 
            red = morecolor(red,inc)
            blue = morecolor(blue,inc)
            green = morecolor(green,inc)
        end
        return color(red, green, blue)
    end
    
    function morecolor(c,inc)
        c = c + inc
        if c>255 or c<0 then
            c = math.random(255)
        end
        return c
    end
    

    That is certainly less disorienting than every triangle being a random colour!

  • Posts: 437

    Yes @mpilgrem ,red,green,blue as globals , i have just reedit the code.

  • Posts: 791

    A slightly different take - adding a texture to each pair of triangles.

    --
    -- Tunnel
    --
    supportedOrientations(LANDSCAPE_ANY)
    displayMode(FULLSCREEN)
    function setup()
        local randomColours = false -- False for different shading option
        local pointNo = 30         -- No. of points in cross-section
        local radius = 30          -- Cross-section radius
         red   = math.random(255)
     green = math.random(255)
     blue  = math.random(255)  
        path = Pipe.rollerCoaster  -- Choose path for pipe
        speed = 1/20               -- Speed of animation
        c=0
        light = vec3(1, 0, 0) -- Direction to light source
        ambient =0.25         -- Ambient light factor (0 to 1)
        local c = rCol()      -- A random colour
        dt = 1/400            -- No of cross-sections in pipe
        m = mesh()            -- Create a mesh
        m.texture="Cargo Bot:Command Grab"  --set a texture
        local ver = {}        -- Table for vertices
        local col = {}        -- Table for their colours
        for j = 0, 1 - dt, dt do -- For each cross-section in the pipe
            p1 = circle(path(j),
                tangent(dt, path, j), radius, pointNo)
            p2 = circle(path(j+dt),
                tangent(dt, path, j+dt), radius, pointNo)
                local c1, c2   
                c1 = rCol() -- A random colour
                c2=c1
            for i = 1, pointNo do -- For each point in cross-section
                local t1 = p1[i]
                local t2 = p1[(i % pointNo)+1]
                local t3 = p2[i]
                local t4 = p2[(i % pointNo)+1]
                table.insert(ver, t3) -- First triangle
                table.insert(ver, t1)
                table.insert(ver, t2)
                table.insert(ver, t3) -- Second triangle
                table.insert(ver, t2)    
                table.insert(ver, t4)
                
                local idx = m:addRect(0,0,50,50) -- not sure what difference changing these values makes
                m:setRectTex(idx, 0, 0, 1, 1)
                
                if not randomColours then
                    local n1 = (t2 - t1):cross(t3 - t1)
                    n1 = n1:normalize()
                    local n2 = (t2 - t3):cross(t4 - t3)
                    n2 = n2:normalize()
                    local i1 = (math.max(n1:dot(light), 0) * 
                        (1 - ambient) + ambient)
                    local i2 = (math.max(n2:dot(light), 0) * 
                        (1 - ambient) + ambient)
                    c1 = color(c.r*i1, c.g*i1, c.b*i1, 255)
                    c2 = color(c.r*i1, c.g*i1, c.b*i1, 255)
                else
                --already taken care of
                end
                table.insert(col, c1) -- First triangle
                table.insert(col, c1)
                table.insert(col, c1)
                table.insert(col, c2) -- Second triangle
                table.insert(col, c2)
                table.insert(col, c2)
            end
        end
        m.vertices = ver -- Set vertices
        m.colors = col   -- Set their colours
     
        
    end
    
    function draw()
        t = ElapsedTime * speed
        background(0) 
        local eye = eye(t) -- Get position of the eye
        local dir = eye + tangent(dt, path, t)
        pushMatrix()
        perspective() -- Set the default perspective
        camera(eye.x, eye.y, eye.z, -- Set eye location
            dir.x, dir.y, dir.z,    -- Set direction of eye
            0, 1, 0)                -- Set orientation of eye
        m:draw()                    -- Draw mesh
        popMatrix()
    end
    
    Pipe = {}
    
    -- Function to define a path of the pipe
    function Pipe.rollerCoaster(t)
        local a = t * 2 * math.pi
        local r = 300 
        local y = r/2 * math.sin(3*a)
        local x = r * math.cos(a)
        local z = r * math.sin(2*a)
        return vec3(x, y, z)
    end
    
    -- Function to define a path of the pipe
    function Pipe.knot(t)
        local a = t * 2 * math.pi * 3
        local r = 200 * (1 + math.cos(5 * a / 3))
        local y = 100 * math.sin(5 * a / 3)
        local x = r * math.cos(a)
        local z = r * math.sin(a)
        return vec3(x, y, z)
    end
    
    -- Function to estimate tangent of f(t) at t
    function tangent(delta, f, t)
        local u = t - delta/2
        local v = t + delta/2
        local df = f(v) - f(u)
        return df:normalize()
    end
    
    -- Function returns points of next cross-section
    local ov2 = nil
    function circle(origin, dir, radius, pointNo)
        local points = {}
        local v1 = dir:cross(ov2 or vec3(1, 0, 0))
        local v2 = dir:cross(v1)
        v1 = v1:normalize()
        v2 = v2:normalize()
        ov2 = -v2
        for i = 0, pointNo - 1 do
            local a = i/pointNo * 2 * math.pi
            local p = origin + 
                (v1 * math.cos(a) + v2 * math.sin(a)) * radius
            table.insert(points, p)
        end
        return points
    end
    
    -- Returns a random colour
    function rCol()
        local red = math.random(255)
        local green = math.random(255)
        local blue = math.random(255)    
        return color(red, green, blue)
    end
    
    
    
    
    -- Returns position of eye
    function eye(t)
        return path(t)
    end
    
    
  • edited August 2012 Posts: 563

    @mpilgrem - absolutely brilliant! What about turning this into a game with a Fantastic Voyage (http://en.wikipedia.org/wiki/Fantastic_Voyage) theme? You just need to add some bacteria and virus to shoot at and blood cells to avoid.

  • Posts: 2,161

    Something along these lines?:

  • Posts: 437

    Is not that a little dark, @West?

  • Posts: 791

    Increase the value of ambient to lighten @juaxix

    Make randomColours true to get back to the more colourful version

    These are part of @mpilgrem's original posting

  • edited August 2012 Posts: 437

    Thanks @West , i have not started yet with meshes, Btw, here is the video with the colors stuff

    http://yfrog.us/n1gd9lnjbcxgdevjqutajonfz

  • JohnJohn Admin Mod
    Posts: 635

    Trippy

Sign In or Register to comment.