Converting meshes to models

@piinthesky Are you creating a mesh and converting it to a model for every single sphere? I’m pretty sure that you don’t need to do that. I’ll need to experiment, but I think that once the model is created then you can use it for as many entities as you like.

@LoopSpace ahhh, yes i was stupid! Just using the same model for all sphere.entities works and is even faster.

@piinthesky That’s good to know. I still don’t feel that I have completely figured out the basics of craft.

Every time I think I’ve understood what’s going on in Codea, they add new features! “Fortunately”, none of my iPads will do Face AR so I can’t play with that.

I was going to mention it but it looks like you guys already figured it out. You can use the same model for as many entities as you like :smile:

@LoopSpace what stuff would you say you find the most difficult to grasp with Craft?

@John if you’re asking questions about Craft, would you happen to have something like a flowchart that shows how Craft is layed out. For instance you start with craft.scene and from there you have aaa bbb ccc . From aaa bbb ccc you have other things etc. I don’t have a good understanding of how Craft is layed out.

@John - pardon my ignorance but is there a simple way of scaling a model (around its core central point) so individual spheres as mentioned above could be modified quickly?

On the same theme is there a simple way of moving a model by reference to its core central point?

I’m about to play with a few model ideas and you could save me a little time.

@dave1707 That’s a good idea, I’ll see what I can do

@Bri_G, I assume you mean the pivot point when you say core central point. All models pivot around zero, which for most things is right in the middle (cubes, sphere, in particular).
You can use myEntity.scale = vec3(0.5, 0.5, 0.5) to scale something down to 50% size. Each entry in vec3 is a different axis, so if you want to scale non-uniformly then you can use different amounts. For positioning you can use myEntity.position and rotation using myEntity.rotation.
If you want to modify where the centre of a model is there are a few options:

  • modify where the centre is by changing the model vertices
  • manually adjust the position you are setting
  • use an empty entity as a parent and adjust the position of the child entity

The 3rd option is nice in that scaling the parent will scale the child as if you had adjusted the model’s pivot point.

Here’s an example of scaling and positioning some spheres:

-- Scale Test

-- Use this function to perform your initial setup
function setup()
    print("Hello Scaling!")
    
    scene = craft.scene()
    -- Move the camera back and rotate 180 degrees to face the center of the world
    scene.camera.z = 15
    scene.camera.rotation = quat.eulerAngles(0,180,0)
    
    sphere = craft.model("Primitives:Sphere")
    
    -- Models come with a default material loaded from their file (usually Materials:Specular)
    sphere:getMaterial().diffuse = color(213, 175, 12, 255)
    
    spheres = {}
    
    -- Create 10 entities that all use the same sphere model
    for i = 1, 10 do 
        local s = scene:entity()
        s.model = sphere
        -- Adjust position to keep them spaced evenly relative to the center of the world
        s.position = vec3((-10 * 0.5 + i), 0, 0)
        table.insert(spheres, s)
    end
    
    -- I forgot to document this but models have a bounds object
    -- Bounds includes an offset and size, min and max location 
    -- which is in local space relative to the vertices in the model
    print("Bounds (offset, size): ", sphere.bounds.offset, sphere.bounds.size)
    
end

-- This function gets called once every frame
function draw()
    
    -- Update sphere scale based on position and time using sine wave
    local v = vec3(1,1,1)
    for i = 1, #spheres do 
        spheres[i].scale = v * math.abs(math.sin(i*0.25 + ElapsedTime) * 0.5)
    end
    
    scene:update(DeltaTime)
    scene:draw()    
end

@John while we are on the subject of scaling! I reported previously there is an bug with scaling when in AR mode-if the scaling is small all hell breaks lose! I made a video to convince you…

https://youtu.be/CEEBACmSYCY

@piinthesky How are you doing the scaling, can you show me the code?

@John - thanks for the feedback and example, I want to move models in a figure of 8 path away from the screen then back rotating through 360 as it moves. Should be able to figure it out now. Thanks.

@John here is the AR example i modified for scaling. Myscene is the parent of each block. Myscene is then scaled in the parameter slider…

-----------------------------------------
-- AR
-- Written by John Millard
-----------------------------------------
-- Description:
-- A basic Augmented Reality demo using ARKit internally.
-- Use scene.ar to setup and pause AR* mode.
--
-- * Please note that only devices with an A9 processor or above support AR.
--   This is an iOS 11 only feature.
-----------------------------------------
 

displayMode(FULLSCREEN)

function setup()
    -- Create a new craft scene
    scene = craft.scene()
    scene.sun:get(craft.light).intensity = 0.7
    myscene=scene:entity()
    parameter.number("sceneScale",0,2,1, function(c) myscene.scale=vec3(1,1,1)*c end)

    if craft.ar.isSupported then
        -- Enable AR session
        scene.ar:run()

        -- Keep a list of detected planes
        planes = {}
        
        -- Option to turn plane detection on and off
        parameter.boolean("PlaneDetection", true, function(b)
            scene.ar.planeDetection = b
        end)
        
        -- Option to draw any detected planes using camera rendering mask
        parameter.boolean("DrawPlanes", true, function(b)
            local c = scene.camera:get(craft.camera)
            if b then
                c.mask = ~0
            else
                c.mask = 1
            end
        end)
        
        parameter.boolean("DrawPointCloud", true)

        local grid = readImage("Project:GridWhite")
        
        scene.ar.didAddAnchors = function(anchors)
            for k,v in pairs(anchors) do
                local p = scene:entity():add(Plane, v, grid)
                planes[v.identifier] = p
            end
        end
        
        scene.ar.didUpdateAnchors = function(anchors)
            for k,v in pairs(anchors) do
                local p = planes[v.identifier]
                p:updateWithAnchor(v)
            end
        end
        
        scene.ar.didRemoveAnchors = function(anchors)
            for k,v in pairs(anchors) do
                local p = planes[v.identifier]
                p.entity:destroy()
                planes[v.identifier] = nil
            end
        end   

        trackingState =
        {
            [AR_NOT_AVAILABLE] = "Not Available",
            [AR_LIMITED] = "Limited",
            [AR_NORMAL] = "Normal"
        }

        cross = image(16,16)
        setContext(cross)
        pushStyle()
        fill(255, 198, 0, 255)
        noStroke()
        rectMode(CENTER)
        rect(cross.width/2, cross.height/2, 3, cross.height)
        rect(cross.width/2, cross.height/2, cross.width, 3)
        popStyle()
        setContext()

    end
    parameter.action("ar pause", function()  scene.ar:pause() end)
    parameter.action("ar run", function()  scene.ar:run() end)
end

function update(dt)
    scene:update(dt)   
end

-- Called automatically by codea 
function draw()
    update(DeltaTime)

    -- Draw the scene
    scene:draw()	
    
    local status = nil
    if craft.ar.isSupported then
        status = trackingState[scene.ar.trackingState]
        
        if DrawPointCloud then
            local c = scene.camera:get(craft.camera)
            for k,v in pairs(scene.ar.points) do
                local p = c:worldToScreen(v)
                sprite(cross, p.x, p.y)
            end
        end
    else
        status = "AR Not Supported"
    end
    fill(255, 255, 255, 255)
    text(status, WIDTH/2, HEIGHT - 50)
    
end

function touched(touch)
    if craft.ar.isSupported and touch.state == BEGAN then
        local results = scene.ar:hitTest(
            vec2(touch.x, touch.y),
            AR_EXISTING_PLANE_CLIPPED)
        
        for k,v in pairs(results) do
            local e = scene:entity()
            e.parent=myscene
            local cube = e:add(Cube, v.position + vec3(0,0.5,0), 0.1)
            break
        end
    end
end

@john you could also add an ar.pause() and ar.run() to the above to see the problem with restarting after a pause.

@John did you get a chance to look into the AR scaling issue-illustrated in the video above? I suspect this is the origin of many of the unstable AR problems i am experiencing.

I also think applyTorque does not work in AR for some reason-can you confirm or not?

It appears you fixed the ar.pause/ar.run issue?

@piinthesky I think @John did fix the ar.pause / run issue. We’ll look into the scaling soon

@piinthesky Can I ask what your intended effect is for globally scaling the AR world and applying physics at the same time? Scaling multiple physics objects arbitrary and having them behave is tricky, and even engines like Unity don’t necessarily handle this perfectly.

I can see that there’s definitely a problem with physics scaling as it’s causing non-uniform warping and the physics isn’t syncing correctly - so I’m attempting to figure out what’s causing that. It shouldn’t have anything to do with AR since that only effects the camera/view transform and nothing else.

@john i am (still!) developing a neutrino telescope app, see video here…

https://youtube.com/watch?v=kqm7ndKuxYg

I am now working on an AR view of it, see here…

https://twitter.com/paschalcoyle/status/1049277318185865216?s=21

The AR view applies a global scaling to make it fit in the real world (it is a kilometer cubed in real size). When i try to implement the submarine in AR as a dynamic body, it displays crazily -a bit like the cubes do in the video in the earlier post. It seems dynamic bodies and scaling and AR are not happy together at the moment.

I use a dynamic body with applyForce and applyTorque to control the submarine movement (this does works in normal 3D). If you think the prospects of fixing this are dim, i could probably switch back to using a kinematic body and handle the flight mechanics using the ignatz/loopspace flight class.

@piinthesky that’s amazing, do you actually work with a neutrino telescope?

yes, its 2,500m deep at the bottom of the Mediterranean Sea and studies your sky in Australia! (the neutrinos pass through the Earth no problem), follow me on twitter!

@LoopSpace when i try to use an open ended cone from your 3d pseudoMesh library, which is then converted to a craft model with ‘toModel()’. I observe that only the inside of the cone is ever visible. Surprisingly, if i apply ‘invertNormals()’ it does not seem to have any effect? Am i doing something wrong? How can i see the exterior surface of the open ended cone model?

@piinthesky Are you doing “invertNormals” before converting to a model?

Can you post a small example?