Howdy, Stranger!

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

Third person 3d

in General Posts: 50

I want the box to move in accordance to the height of the terrain. This is my code.

-- Use this function to perform your initial setup
displayMode(FULLSCREEN)
function setup()
    stick = Stick()

    pylon = Wall("Cargo Bot:Crate Red 2")
    wall = Wall("Cargo Bot:Crate Yellow 2")
    hero = Hero(1,0,0)

    TO_DEG = 180/math.pi
    sin,cos,rad=math.sin,math.cos,math.rad
    --UserDefined vars
    TerrainRes=64 --Resolution of terrain
    TerrainSize=9--Size in x and z
    TerrainHeight=4
    --Movement
    Angle=vec2(0,0)
    parameter.number("X",-1,2,1)
    parameter.number("Y",-1,2,1)
    parameter.number("Z",-1,2,0)
    --Variables
    Ires=TerrainSize/TerrainRes
    EpicTerrain=image(TerrainRes/2,TerrainRes/2)
    setContext(EpicTerrain)
    sprite("Documents:height amp") --IMPORTANT! Your heightmap here!!
    setContext()
    --Meshing
    local X,Index,px,py,y1,y2,y3,y4
    m=mesh()
    verts={}
    for x=1,TerrainRes-1 do
        X=(x-1)*(TerrainRes-1)*6+1
        px=(x-1)/TerrainRes px=px*TerrainSize
        for y=1,TerrainRes-1 do
            Index=X+(y-1)*6
            py=(y-1)/TerrainRes py=py*TerrainSize
            --All the heights
            y1=color(EpicTerrain:rawGet(x,y)).x/255*TerrainHeight
            y2=color(EpicTerrain:rawGet(x+1,y)).x/255*TerrainHeight
            y3=color(EpicTerrain:rawGet(x,y+1)).x/255*TerrainHeight
            y4=color(EpicTerrain:rawGet(x+1,y+1)).x/255*TerrainHeight
            --Constructing the vertices
            verts[Index]=vec3(px,y1,py)
            verts[Index+1]=vec3(px+Ires,y2,py)
            verts[Index+2]=vec3(px+Ires,y4,py+Ires)
            verts[Index+3]=vec3(px+Ires,y4,py+Ires)
            verts[Index+4]=vec3(px,y3,py+Ires)
            verts[Index+5]=vec3(px,y1,py)
        end
    end
    m.vertices=verts
    m.shader=shader(MSV,MSF)
    m.shader.TerrainSize=TerrainSize*1.5
end



-- This function gets called once every frame
function draw()
    background(0)
    local TO_DEG = TO_DEG
    local hero = hero

    perspective(60)
    camera(hero.x, 2, 1+hero.z, hero.x, 1, hero.z, 0, 1, 0)
    m:draw()
-- Draw world


-- Draw hero
    translate(hero.x, hero.y, hero.z)
    rotate(stick.direction*TO_DEG, 0, 1, 0)

    -- roll animation
    if stick.active then
        rotate(-ElapsedTime*10*TO_DEG, 0, 0, 1)
    end

    scale(.25, .25, .25)
    hero:draw()

-- Restore orthographic projection

    -- fade out overlay

    if stick.active then
        local ceil = math.ceil

        -- move hero based on stick direction
        local mvtx = math.cos(stick.direction)/50*stick.dist
        local mvtz = -math.sin(stick.direction)/50*stick.dist
        hero.x = hero.x + mvtx
        hero.z = hero.z + mvtz
        hero.y = 1
        -- convert to table coordinates
        hero.px = ceil(hero.x - .5)
        hero.py = ceil(hero.z - .5)

        -- lazy collision check
    end
    ortho()
    resetMatrix()
    viewMatrix(matrix())
    sprite(EpicTerrain,0,0,300,300)
end

function touched(touch)
    stick:touched(touch)
end

--# World



--# Hero
Hero = class()

function Hero:init(x,y,z)
    self.x, self.y, self.z = x,y,z
    self.px, self.py = math.ceil(.5+x), math.ceil(.5+z)

    self.mdl = Wall("Cargo Bot:Crate Blue 2")
end

function Hero:draw()
    self.mdl:draw()
end


--# Wall
Wall = class()


function Wall:init(tex)
    -- all the unique vertices that make up a cube
    local vertices =
    {
        vec3(-0.5, -0.5,  0.5), -- Left  bottom front
        vec3( 0.5, -0.5,  0.5), -- Right bottom front
        vec3( 0.5,  0.5,  0.5), -- Right top    front
        vec3(-0.5,  0.5,  0.5), -- Left  top    front
        vec3(-0.5, -0.5, -0.5), -- Left  bottom back
        vec3( 0.5, -0.5, -0.5), -- Right bottom back
        vec3( 0.5,  0.5, -0.5), -- Right top    back
        vec3(-0.5,  0.5, -0.5), -- Left  top    back
    }

    -- now construct a cube out of the vertices above
    local verts =
    {
        -- Front
        vertices[1], vertices[2], vertices[3],
        vertices[1], vertices[3], vertices[4],
        -- Right
        vertices[2], vertices[6], vertices[7],
        vertices[2], vertices[7], vertices[3],
        -- Back
        vertices[6], vertices[5], vertices[8],
        vertices[6], vertices[8], vertices[7],
        -- Left
        vertices[5], vertices[1], vertices[4],
        vertices[5], vertices[4], vertices[8],
        -- Top
        vertices[4], vertices[3], vertices[7],
        vertices[4], vertices[7], vertices[8],
       -- Bottom
        vertices[5], vertices[6], vertices[2],
        vertices[5], vertices[2], vertices[1],
    }

    -- all the unique texture positions needed
    local texvertices =
    {
        vec2(0,0),
        vec2(1,0),
        vec2(0,1),
        vec2(1,1)
    }

    -- apply the texture coordinates to each triangle
    local texCoords =
    {
        -- Front
        texvertices[1], texvertices[2], texvertices[4],
        texvertices[1], texvertices[4], texvertices[3],
        -- Right
        texvertices[1], texvertices[2], texvertices[4],
        texvertices[1], texvertices[4], texvertices[3],
        -- Back
        texvertices[1], texvertices[2], texvertices[4],
        texvertices[1], texvertices[4], texvertices[3],
        -- Left
        texvertices[1], texvertices[2], texvertices[4],
        texvertices[1], texvertices[4], texvertices[3],
        -- Top
        texvertices[1], texvertices[2], texvertices[4],
        texvertices[1], texvertices[4], texvertices[3],
        -- Bottom
        texvertices[1], texvertices[2], texvertices[4],
        texvertices[1], texvertices[4], texvertices[3],
    }

    self.model = mesh()
    self.model.vertices = verts
    self.model.texture = tex
    self.model.texCoords = texCoords
    self.model:setColors(255,255,255,255)
end

function Wall:draw()
    self.model:draw()
end
--# Floor


--# Stick
Stick = class()

function Stick:init()
    self.direction = 0
    self.dist = 0

    self.active = false
    self.origin = vec2(150, 150)
    self.center = self.origin
    self.pos = self.origin


end


function Stick:touched(touch)
    if touch.state == BEGAN then
        self.center = vec2(touch.x, touch.y)
        self.active = true
    end

    self.pos = vec2(touch.x, touch.y)
    self.direction = math.atan2(self.pos.y - self.center.y, self.pos.x - self.center.x)

    self.dist = math.min(2, self.pos:dist(self.center)/32)

    if touch.state == ENDED then
        self.center = self.origin
        self.pos = self.center
        self.active = false
    end


end
MSV=[[
uniform mat4 modelViewProjection;
attribute vec4 position;
varying vec3 Pos;

void main() {
    Pos=position.xyz;
    gl_Position=modelViewProjection*position;
}
]]

MSF=[[
precision highp float;
varying vec3 Pos;
uniform vec3 Player;
uniform float TerrainSize;

void main() {
    gl_FragColor=vec4(pow(vec3(length(Player-Pos)/TerrainSize),vec3(0.45)),1.);
}
]]

Comments

  • edited March 19 Posts: 923

    @dmoeller - what you are doing is very similar to something I am working on. I put one of my heightmap in it but the range is too high, looks like yours is set to 4 and mine is set to 255. Since the terrain is not coloured it’s very difficult to asses the heights in general. But, in my case, the hero as you call him will stay in one place and the terrain will move downwards.

    You may need to change the camera viewpoint to see the effect more. Also I’m assuming you will be using a shadow to show the depth etc.

  • Posts: 50

    How do you color the terrain?

  • Posts: 923

    @dmoeller - I read the colour of the heightmap and attribute that colour to each of vertices for the two triangles in each rectangle used for the terrain - in a mesh. You could use shaders for this, it’s a bit of a patchwork effect, you can reduce that by narrowing the colour difference across your terrain. What kind of terrain have you in mind?

    You can also apply textures to the terrain to pattern the areas.

    I have also experimented with gradient shading across the terrain but so far I’m not impressed, it sort of glows and features are blended away.

    Also it’ better if you keep your hero central and scroll your landscape.

  • Posts: 50

    I want to make a 3d person shooter with grassy terrain, could I see your code so I can build off it?

  • Posts: 923
    @dmoeller - my code is not that advanced, it would be better to identify component parts and build them up in the forum then everyone can learn from them.

    If you'd like to start with a terrain give us an outline of what you need and your problems, a demo of something similar to your own terrain for us to start with. There are lots of experienced programmers on this forum, so progress should be good.

    Are you planning to base it on Craft or mainly on meshes?

    Also have you checked out Ignatz's post on Coolcodea - covers most of what you'll need.
  • Posts: 50

    First I would want to make a noise function for the terrain and shade it with a grassy textur

  • Posts: 50

    This can be the texture

  • Posts: 50

    I have checked out @Ignatz posts on cool codea but, It always says invalid sprite pack name

  • Posts: 923

    @dmoeller - right, thanks for the input. The first thing to do is rename your texture to something easier say grass01, and copy it to your documents folder or Dropbox root folder. Have you got a small heightmap to use as a demo?

    I’ll start looking at code.

  • Posts: 50

    My height map was going to be a 3d noise function

  • edited March 20 Posts: 923

    @dmoeller - which module of Ignatz were you referring to with the spritepack error?

  • Posts: 50

    Any one with this function

    function LoadImage(fileName,url)
            local i=readImage(fileName)
            if i~=nil then return i end 
            --not found, we need to download, add to queue (ie table)
            if imageTable==nil then imageTable={} end
            imageTable[#imageTable+1]={name=fileName,url=url}
            print('Queueing',fileName)
            imageStatus='Loading'
            --if the first one, go ahead and download
            if #imageTable==1 then 
                http.request(imageTable[1].url,ImageDownloaded) 
                print('loading',imageTable[1].name)
            end
    end
    
  • edited March 20 Posts: 923

    @dmoeller - That routine looks like one he used for setting up his 3D demos with a host of graphics for building up a village which you could walk around. Is that what you’re baseing your RPG on?

    The graphics there are all downloaded from a web page, if the web page is deleted or moved address you won’t be able to access the graphics. I’ll check this out.

    Edit: Yeah, that routine is part of several routines to download specific graphics from his photobucket drive. Have you downloaded all of the graphics he has on there for his early 3D terrains? If so I believe his code also downloads all his graphics down to you iPad, you should be able to address them from your own storage if so. I have them all in my Dropbox account, you may find them in your Documents resource.

  • Posts: 50

    Sorry, I posted the wrong function, this is the one my iPad doesn’t like

    function ImageDownloaded(img)
        print(imageTable[1].name,'loaded')
        saveImage(imageTable[1].name,img)  --save
        table.remove(imageTable,1)
        --load next one if we have any more to do
        if #imageTable>0 then
            http.request(imageTable[1].url,ImageDownloaded)
            print('loading',imageTable[1].name)
        else
            LoadImages()
        end
    end
    
  • Posts: 50

    How do you make a 3d noise function for terrain?

  • Posts: 50

    I tried modifying @Ignatz code and this is what I got, for some reason the table is nil, could you help? I attached the pictures I used in the setup function

    Here is my code

  • Posts: 50
    --# Main
    function setup()
        gravel=readImage("Documents:gravel")
        tree=readImage("Documents:tree")
        grass=readImage("Documents:grass")
        imageStatus="Ready"
        setup2()
    end
    
    function setup2()
        parameter.integer("Viewpoint",-2000,2000,20)
        speed,angle=0,0
        ds,da=0,0
        posX,posY,posZ=-20,0,10 --starting position
        rad=math.pi/180
        meshTable={}
        count=0
        meshTable[1],meshTable[2]={},{}
        AddLevel(-500,0,0,1000,1000,gravel,.1)
        HM={} --holds height maps, one for each terrain area we build -- NEW
        --add a terrain area --NEW
        AddTerrain({x=-400,y=0.5,z=100,width=800,depth=800,tileSize=50,minY=10,maxY=100,random=false,
                    noiseLevel=.2,noiseStep=.5,img=grass,scaleFactor=.1,heightMaps=HM})
        --add 200 trees
        for i=1,200 do
            local x=math.random(-375,375)
            local z=math.random(150,750)
            local w=math.random(20,60)
            AddItem(x,0,z,w,tree) --rotating to face us
        end
        count=0
        FPS=60
    end
    
    function draw()
        if imageStatus~="Ready" then return end
        count=count+1
        background(220)
        perspective(45,WIDTH/HEIGHT)
        if Viewpoint<10 then Viewpoint=10 end
        angle=angle+da*DeltaTime
        posX,posZ=posX+ds*DeltaTime*math.sin(angle*rad),posZ+ds*DeltaTime*math.cos(angle*rad)
        local h0=posY  --NEW
        posY=math.max(Viewpoint,HeightAtPos(posX,posZ)+10) --NEW
        local h1=posY  --NEW
        --try to look up if climbing or down if descending --NEW
        if posY==Viewpoint then lookY=20 else lookY=(h1-h0)*100/ds+10 end
        --look in the same direction as we are facing
        lookX,lookY,lookZ=posX+1000*math.sin(angle*rad),20,posZ+1000*math.cos(angle*rad)  
        camera(posX,posY,-posZ,lookX,lookY,-lookZ, 0,1,0)
        if count%20==1 then 
            table.sort(meshTable[2],
            function(a,b) return 
                vec2(posX,-posZ):dist(vec2(a.pos.x,-a.pos.z))>vec2(posX,-posZ):dist(vec2(b.pos.x,-b.pos.z)) end)
        end
        for k=1,2 do
            for i,m in pairs(meshTable[k]) do
                --rotate free standing objects if required, so they face us
                if m.rotate==true then
                    pushMatrix()
                    translate(m.pos.x,m.pos.y,-m.pos.z)
                    local dx,dz=m.pos.x-posX,-m.pos.z+posZ
                    local ang=math.atan(dx/-dz)/rad
                    rotate(-ang,0,1,0)
                    m:draw()
                    popMatrix() 
                elseif m.ang==nil then m:draw()
                else
                    pushMatrix()
                    translate(m.pos.x,m.pos.y,-m.pos.z)
                    rotate(-m.ang,0,1,0)
                    m:draw()
                    popMatrix() 
                end
            end
        end
        ortho() --this is needed to get text written on the screen
        viewMatrix(matrix()) --and this
        pushStyle()
        fill(0)
        fontSize(18)
        strokeWidth(3)
        textMode(CORNER)
        text("x="..string.format("%  d",posX),50,HEIGHT-70)
        text("y="..string.format("%  d",posY),50,HEIGHT-90)
        text("z="..string.format("%  d",posZ),50,HEIGHT-110)
        popStyle()
    end
    
    -- x,z = bottom left corner
    -- y = height around the edges
    -- w,d = width and depth of area to be terrained (pixels)
    -- p = pixels per tile
    -- f = minimum height (pixels), can be lower than y
    -- h = max height (pixels)
    -- r = whether to randomise terrain each run (true/false)
    -- n = noise level (bigger numbers result in bumpy terrain, smaller gives smoother results)
    -- tbl = table of heights, if provided
    -- img = image or string name of image (do not include library name)
    -- sc = image scaling factor (see above) 0-1
    -- hm = height map storing heights of each point in 
    -- ns = the fraction by which noise level increases for each tile as we go deeper into the terrain
    --      eg a value of 0.3 means that the outside ring of tiles has nil noise (as always, so these tiles
    --      exactly meet the surface around), the next ring of tiles has noise of 0.3 of the full level,
    --      the third ring of tiles has noise of 0.6, and so on, up to a maximum of 1.0. The bigger ns, the
    --      the more you will get cliffs at the edges of the terrain
    
    function AddTerrain(...)
        local x,y,z,w,d,p,f,h,r,n,tbl,img,sc,hm,ns=Params(
            {"x","y","z","width","depth","tileSize","minY","maxY","random","noiseLevel",
             "heightTable","img","scaleFactor","heightMaps","noiseStep"},arg) 
        local nw,nd=math.floor(w/p),math.floor(d/p) --number of tiles in each direction
        --if no table of heights provided, generate one with noise
        if tbl==nil then
            n=n or 0.2 --default noise level
            tbl1,tbl2={},{} 
            --noise starts at 0 on the outside, increases by the step as we move inward, max of 1
            --noise is nil at edge, increases by 30% per tile inwards, to 100% 
            local min,max=9999,0
            --if user wants a random result each time. add a random number to the noise results
            if r==true then rnd=math.random(1,10000) else rnd=0 end
            for i=1,nw+1 do
                tbl1[i],tbl2[i]={},{}
                for j=1,nd+1 do
                    --noise fraction for this tile, based on how close to the edge it is
                    --this formula counts how many rows in from the edge this tile is
                    tbl1[i][j]=math.min(1,math.min(i-1,j-1,nw+1-i,nd+1-j)*ns)
                    --the noise itself
                    tbl2[i][j]=noise(rnd+i*n, rnd+j*n) 
                    --keep track of min and max values of noise
                    if tbl2[i][j]<min then min=tbl2[i][j] end
                    if tbl2[i][j]>max then max=tbl2[i][j] end
                end
            end
            --now go back through the whole array and scale it
            --we know the user wants values between f and h
            --we know our noise varies between min and max
            --so now we pro rate all our values so they vary between f and h, based on the noise values
            for i=1,nw+1 do
                for j=1,nd+1 do
                    local f1=y
                    --pro rate
                    local f2=f+(h-f)*(tbl2[i][j]-min)/(max-min)
                    --now apply noise fraction, to reduce noise around the edges
                    tbl2[i][j]=f1*(1-tbl1[i][j])+f2*tbl1[i][j]
                end
            end       
        end
        --store details for later use in determining height
        table.insert(hm,{x1=x,z1=z,x2=x+w,z2=z+d,p=p,t=tbl2})
        --create the vectors and mesh
        local wx,wz=img.width*sc,img.height*sc
        v,t={},{}
        for i=1,nw do
            for j=1,nd do
                local x1,x2=x+(i-1)*p,x+i*p  local x3,x4=x2,x1
                local y1,y2,y3,y4=tbl2[i][j],tbl2[i+1][j],tbl2[i+1][j+1],tbl2[i][j+1]
                local z1,z3=z+(j-1)*p,z+j*p  local z2,z4=z1,z3
                v[#v+1]=vec3(x1,y1,-z1) t[#t+1]=vec2(x1/wx,z1/wz)  --bottom left
                v[#v+1]=vec3(x2,y2,-z2) t[#t+1]=vec2(x2/wx,z2/wz)  --bottom right
                v[#v+1]=vec3(x3,y3,-z3) t[#t+1]=vec2(x3/wx,z3/wz)  --top right
                v[#v+1]=vec3(x3,y3,-z3) t[#t+1]=vec2(x3/wx,z3/wz)  --top right
                v[#v+1]=vec3(x4,y4,-z4) t[#t+1]=vec2(x4/wx,z4/wz)  --top left
                v[#v+1]=vec3(x1,y1,-z1) t[#t+1]=vec2(x1/wx,z1/wz)  --bottom left
            end 
        end
        local m=mesh()
        m.texture=img
        m.vertices=v
        m:setColors(color(255))
        m.texCoords=t 
        m.pos=vec3(x,y,z)
        m.shader = shader(autoTilerShader.vertexShader, autoTilerShader.fragmentShader)
        table.insert(meshTable[1],m)
    end
    
  • Posts: 50
    --calculates height at x,z
    function HeightAtPos(x,z)
        --identify the location and calculate height
        local h=0 --set default as 0
        for i,v in pairs(HM) do  --look in each terrain area
            if x>=v.x1 and x<=v.x2 and z>=v.z1 and z<=v.z2 then --if in this area...
                --calc which square we are in
                local mx,mz=1+math.floor((x-v.x1)/v.p),1+math.floor((z-v.z1)/v.p)
                --use bilinear interpolation (most common method) for interpolating 4 corner values
                local px,pz=1+(x-v.x1)/v.p-mx,1+(z-v.z1)/v.p-mz
                h=v.t[mx][mz]*(1-px)*(1-pz)+
                        v.t[mx+1][mz]*px*(1-pz)+
                        v.t[mx+1][mz+1]*px*pz+
                        v.t[mx][mz+1]*(1-px)*pz
                break
            end
        end
        return h
    end
    
    function AddItem(x,y,z,w,i,r) --centred on x
        y=HeightAtPos(x,z)
        local h=i.height*w/i.width
        local m=mesh()
        m.texture=i
        local v,t={},{}
        v,t=AddImage(-w/2,0,0,w,h,0,v,t)
        m.pos=vec3(x,y,z)
        if r~=nil then m.ang=r else m.rotate=true end
        m.vertices=v
        m:setColors(color(255))
        m.texCoords=t 
        table.insert(meshTable[2],m)
    end
    
    function AddImage(x,y,z,w,h,d,v,t)
        v[#v+1]=vec3(x,y,z)  t[#t+1]=vec2(0,0)
        v[#v+1]=vec3(x+w,y,z-d)  t[#t+1]=vec2(1,0)
        v[#v+1]=vec3(x+w,y+h,z-d)  t[#t+1]=vec2(1,1)
        v[#v+1]=vec3(x+w,y+h,z-d)  t[#t+1]=vec2(1,1)
        v[#v+1]=vec3(x,y+h,z)  t[#t+1]=vec2(0,1)
        v[#v+1]=vec3(x,y,z)  t[#t+1]=vec2(0,0)
        return v,t
    end
    
    function AddLevel(x,y,z,w,d,i,s)
        local m=mesh()
        m.texture=i
        local v,t={},{}
        local nx,nz=w/i.width/s,d/i.height/s
        v[#v+1]=vec3(x,y,-z)  t[#t+1]=vec2(0,0)
        v[#v+1]=vec3(x+w,y,-z)  t[#t+1]=vec2(nx,0)
        v[#v+1]=vec3(x+w,y,-z-d)  t[#t+1]=vec2(nx,nz)
        v[#v+1]=vec3(x+w,y,-z-d)  t[#t+1]=vec2(nx,nz)
        v[#v+1]=vec3(x,y,-z-d)  t[#t+1]=vec2(0,nz)
        v[#v+1]=vec3(x,y,-z)  t[#t+1]=vec2(0,0)
        m.vertices=v
        m:setColors(color(255))
        m.texCoords=t 
        m.pos=vec3(x,y,z)
        m.shader = shader(autoTilerShader.vertexShader, autoTilerShader.fragmentShader)
        table.insert(meshTable[1],m)
    end
    
    function touched(touch)
        local center=true
        if touch.x<WIDTH/4 then
            da=da-2
            center=false
        elseif touch.x>WIDTH*3/4 then 
            da=da+2
            center=false
        end
    
        if touch.y<HEIGHT/4 then 
            ds=ds-3
            center=false
        elseif touch.y>HEIGHT*3/4 then 
            ds=ds+3
            center=false
        end
    
        if center then ds=0 da=0 end
    end
    
    function Params(list,tbl) --tbl is params
        if type(tbl[1])=="table" then --was named table
            local t={} --match the named params with the list provided
            for n,v in pairs(tbl[1]) do
                for i=1,#list do
                   if n==list[i] then t[i]=v break end 
                end     
            end  
            return unpack(t)
        else --was an unnamed list, return it as is
           return unpack(tbl) 
        end
    end
    
    function LoadImages()
        imageStatus="Ready" --tells draw it's ok to draw the scene (will be turned off if we have to download images)
        output.clear()
        --pass through Codea name of image and internet url
        --not in Codea, will be downloaded and saved
        grass=LoadImage("Dropbox:3D-grass2",
                "http://i1303.photobucket.com/albums/ag142/ignatz_mouse/map-grass10_zps7573c68c.png")
        gravel=LoadImage("Dropbox:3D-gravel",
                "http://i1303.photobucket.com/albums/ag142/ignatz_mouse/map-gravel11_zpsc3a6ac7d.png")
        tree=LoadImage("Dropbox:3D-tree2",
                "http://i1303.photobucket.com/albums/ag142/ignatz_mouse/map-tree21c_zps655e421c.png")
        if imageStatus=="Ready" then setup2() end
    end
    
    --downloads images one by one
    function LoadImage(fileName,url)
            local i=readImage(fileName)
            if i~=nil then return i end 
            --not found, we need to download, add to queue (ie table)
            if imageTable==nil then imageTable={} end
            imageTable[#imageTable+1]={name=fileName,url=url}
            print('Queueing',fileName)
            imageStatus='Loading'
            --if the first one, go ahead and download
            if #imageTable==1 then 
                http.request(imageTable[1].url,ImageDownloaded) 
                print('loading',imageTable[1].name)
            end
    end
    
    --saves downloaded images
    function ImageDownloaded(img)
        print(imageTable[1].name,'loaded')
        saveImage(imageTable[1].name,img)  --save
        table.remove(imageTable,1)
        --load next one if we have any more to do
        if #imageTable>0 then
            http.request(imageTable[1].url,ImageDownloaded)
            print('loading',imageTable[1].name)
        else
            LoadImages()
        end
    end
    --# Tiler
    autoTilerShader = {
    vertexShader = [[
    //
    // A basic vertex shader
    //
    
    //This is the current model * view * projection matrix
    // Codea sets it automatically
    uniform mat4 modelViewProjection;
    
    //This is the current mesh vertex position, color and tex coord
    // Set automatically
    attribute vec4 position;
    attribute vec4 color;
    attribute vec2 texCoord;
    
    //This is an output variable that will be passed to the fragment shader
    varying lowp vec4 vColor;
    varying highp vec2 vTexCoord;
    
    void main()
    {
        //Pass the mesh color to the fragment shader
        vColor = color;
        vTexCoord = texCoord;
    
        //Multiply the vertex position by our combined transform
        gl_Position = modelViewProjection * position;
    }
    
    ]],
    fragmentShader = [[
    //
    // A basic fragment shader
    //
    
    //Default precision qualifier
    precision highp float;
    
    //This represents the current texture on the mesh
    uniform lowp sampler2D texture;
    
    //The interpolated vertex color for this fragment
    varying lowp vec4 vColor;
    
    //The interpolated texture coordinate for this fragment
    varying highp vec2 vTexCoord;
    
    void main()
    {
        //Sample the texture at the interpolated coordinate
        lowp vec4 col = texture2D( texture, vec2(mod(vTexCoord.x,1.0), mod(vTexCoord.y,1.0))) * vColor;
    
        //Set the output color to the texture color
        gl_FragColor = col;
    }
    
    ]]}
    
  • dave1707dave1707 Mod
    Posts: 6,993

    @dmoeller I modified some code I had. Can you use this. Slide your finger around to move the image. I copied your grass image to my Dropbox folder and named it grass.

    displayMode(FULLSCREEN)
    
    function setup()
        assert(craft, "Please include Craft as a dependency")
        assert(OrbitViewer, "Please include Cameras (not Camera) as a dependency")        
        scene = craft.scene()
        skyMaterial=scene.sky.material
        skyMaterial.sky=color(255, 255, 255, 255)
        skyMaterial.horizon=color(255, 255, 255, 255)
        scene.sun.rotation=quat.eulerAngles(30,30,0)
        v=scene.camera:add(OrbitViewer,vec3(0,0,0), 100, 30, 2000)
        v.rx=25
    
        texture=readImage("Dropbox:grass")  -- your grass image
    
        groundHeight=30
        createGround()
    end
    
    function draw()
        update(DeltaTime)
        scene:draw() 
    end
    
    function update(dt)
        scene:update(dt)
    end
    
    function golfBall(p,c)
        pt=scene:entity()
        pt.position=vec3(p.x,p.y+1,p.z)
        pt.model = craft.model.icosphere(1,2,1)
        pt.material = craft.material("Materials:Standard")
        pt.material.diffuse=color(255)
    end
    
    function createGround()
        local tab,pos,ind,col,uv={},{},{},{},{}
        local h=craft.noise.perlin()
        local step=.1
        local xx=0
        for x=-1,1,step do
            xx=xx+1
            tab[xx]={}
            local zz=0
            for z=-1,1,step do
                zz=zz+1
                local v=h:getValue(x,0,z)
                tab[xx][zz]=vec3(x*300,v*groundHeight,z*300)
                if math.random(100)>80 then -- draw random golf balls on grass
                    golfBall(vec3(x*300,v*groundHeight-.2,z*300))
                end
            end
        end
        for x=1,#tab-1 do
            for z=1,#tab-1 do
                table.insert(pos,tab[x][z])
                table.insert(pos,tab[x+1][z+1])
                table.insert(pos,tab[x][z+1])
                table.insert(pos,tab[x][z])
                table.insert(pos,tab[x+1][z])
                table.insert(pos,tab[x+1][z+1])
            end
        end
        for z=1,#pos do
            table.insert(ind,z)
            table.insert(col,color(255,255,255,255))
        end
        for z=#pos,1,-1 do
            table.insert(ind,z)
        end
        for z=1,#pos/6 do
            table.insert(uv,vec2(0,0))
            table.insert(uv,vec2(1,1))
            table.insert(uv,vec2(0,1))  
            table.insert(uv,vec2(0,0))
            table.insert(uv,vec2(1,0))
            table.insert(uv,vec2(1,1))  
        end
        local pt=scene:entity()
        pt.model = craft.model()
        pt.model.positions=pos
        pt.model.indices=ind
        pt.model.colors=col
        pt.model.uvs=uv
        pt.material = craft.material("Materials:Basic")  
        pt.material.map=texture
    end
    
  • Posts: 923

    Whoa @dave1707 - that’s an excellent example of texturing a mesh, there’s a few learning points for me. I noticed the grass image @dmoeller is using is very big and you picked that up. Your pt.model is very interesting.

    dmoeller, the code you posted is from @Ignatz and I have posted the error on a separate thread - I found that previously but struggled with it. I think it arose from previous updates to Codea. The example posted by @dave1707 shows you how to use the noise function in Craft.

  • dave1707dave1707 Mod
    Posts: 6,993

    Here’s a smaller version of my above code to create a textured terrain.

    displayMode(FULLSCREEN)
    
    function setup()
        assert(craft, "Please include Craft as a dependency")
        assert(OrbitViewer, "Please include Cameras (not Camera) as a dependency")        
        scene = craft.scene()
        skyMaterial=scene.sky.material
        skyMaterial.sky=color(137, 186, 223, 255)
        skyMaterial.horizon=color(98, 142, 229, 255)
        scene.sun.rotation=quat.eulerAngles(30,30,0)
        v=scene.camera:add(OrbitViewer,vec3(0,0,0), 1000, 0, 2000)
        v.camera.farPlane=3000
        v.rx=15
    
        texture=readImage("Dropbox:grass")  -- your grass image
    
        local size=1000
        local groundHeight=200    
        local step=.2
        h=craft.noise.perlin()
        for x=-2,2,step do
            for z=-2,2,step do           
                local y=h:getValue(x,0,z)
                local p1=vec3(x*size,y*groundHeight,z*size)
                y=h:getValue(x+step,0,z)
                local p2=vec3((x+step)*size,y*groundHeight,z*size)
                y=h:getValue(x+step,0,z+step)
                local p3=vec3((x+step)*size,y*groundHeight,(z+step)*size)
                y=h:getValue(x,0,z+step)
                local p4=vec3(x*size,y*groundHeight,(z+step)*size)
                createTile(p1,p2,p3,p4)
            end
        end
    end
    
    function draw()
        update(DeltaTime)
        scene:draw() 
    end
    
    function update(dt)
        scene:update(dt)
    end
    
    function createTile(p1,p2,p3,p4)
        local c=color(255)
        local pt=scene:entity()
        pt.model = craft.model()
        pt.model.positions={p1,p3,p4,p1,p2,p3}
        pt.model.indices={1,2,3,4,5,6,6,5,4,3,2,1}
        pt.model.colors={c,c,c,c,c,c}
        pt.model.uvs={vec2(0,0),vec2(1,1),vec2(0,1),vec2(0,0),vec2(1,0),vec2(1,1)}
        pt.material = craft.material("Materials:Basic")  
        pt.material.map=texture    
    end
    
  • Posts: 923

    @dmoeller the error in Ignatz’s code has been resolved by Loopspace, in the AddTerrain function replace arg with {…} and in the parameter configurations there are three variables posX, posY and posZ which need flooring so replace with math.floor(posX) etc. That allowed the project to run on my iPad.

  • Posts: 50

    I got terrain and moving to work thanks to you and Ignatz But, I want to not be able to pass through trees and have a limit for how fast I can move, here is my code, you will need these pictures

  • Posts: 923

    @dmoeller - got the code running, I think you need Ignatz’s original trees, I’ll see if I can find/post them. On your way forward you might continue to work through Ignatz’s code, it answers a number of issues for you:

    Your initial code above

    Adding trees figures etc
    https://coolcodea.wordpress.com/2013/05/23/62-3d-adding-stand-alone-images-trees-animals/

    Not walking intro trees
    https://coolcodea.wordpress.com/2013/05/30/70-3d-how-not-to-walk-through-solid-objects/

    Items 63 to 70a in Ignatz’s website.

    You could also look at

    His RPG maze
    Items 171 to 178

    His castle in 3D
    Items 203 to 207

    His pool game
    Items 90 to 93

    His tank game
    Items 239 to 245

    His battleship game
    Items 218 to 228

    His racing track game
    Items 35 to 36

    His spitfire vs mescherschmidt flying game
    Item 141 to 149

    Enough to keep you going for months if you are wanting to learn the tricks. Also he has several pdf volumes on 3D programming which are linked to on hi website. If you hit problems we’re always here.

    Also remember when Ignatz wrote all of these it was based on hard detailed work with meshes. Now a lot of that is done for you with Craft, in theory that should be easier to program - you just need to appreciate the basics of 3D programming.

  • Posts: 3

    Greetings good friends suggestion I would like to know if there is any update and where I can get it available for download and make designs in 3d format Thanks I am attentive to any help you can give me

  • edited May 12 Posts: 923
    @3dmodels - thanks for the link to your website, a few interesting models there. Not sure how Codea can help you as there is no printing option other than capturing screens and printing images.
Sign In or Register to comment.