#### Howdy, Stranger!

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

# Converting meshes to models

edited December 2019 Posts: 509

I have quite a lot of code that is heavily invested in meshes which I'd like to adapt to use with Craft, so I came up with a little helper class that can be used as a drop-in for a mesh with a converter to a model for use with Craft.

``````PseudoMesh = class()

function PseudoMesh:init()
self.vertices = {}
self.texCoords = {}
self.normals = {}
self.colors = {}
self.size = 0
end

function PseudoMesh:vertex(k,v)
if v then
self.vertices[k] = v
else
return self.vertices[k]
end
end

function PseudoMesh:normal(k,v)
if v then
self.normals[k] = v
else
return self.normals[k]
end
end

function PseudoMesh:texCoord(k,v)
if v then
self.texCoords[k] = v
else
return self.texCoords[k]
end
end

function PseudoMesh:color(k,v)
if v then
self.colors[k] = v
else
return self.colors[k]
end
end

function PseudoMesh:resize(k)
self.size = k
end

function PseudoMesh:invertNormals()
for k,v in ipairs(self.normals) do
self.normals[k] = -v
end
end

function PseudoMesh:toModel()
local m = craft.model()
local i = {}
local n = #self.vertices
for k=1,n,3 do
if (self.vertices[k+1] - self.vertices[k]):cross(self.vertices[k+2] - self.vertices[k]):dot(self.normals[k+1] + self.normals[k+2] + self.normals[k]) < 0 then
table.insert(i,k)
table.insert(i,k+1)
table.insert(i,k+2)
else
table.insert(i,k)
table.insert(i,k+2)
table.insert(i,k+1)
end
end
m.positions = self.vertices
m.normals = self.normals
m.uvs = self.texCoords
m.colors = self.colors
m.indices = i
return m
end
``````

Use as:

``````m = PseudoMesh()
-- set up m as if it were a mesh
e = scene:entity()
e.model = m:toModel()
``````

The `invertNormals` is because meshes would look the same from both sides but models are viewable from one only, so it may be that ones mesh is inside out. This flips it round.

As an example, I've adapted my old Roller Coaster code to Craft using this technique (@Simeon, @John would you consider replacing the old code with a Crafty update?).

«1

Posts: 5,708

@LoopSpace would there be value in having something like this built-in?

We would totally love to replace your Roller Coaster with a Craft-version! Share the zip here.

• Posts: 194

@Simeon or keep both, for reference?

• edited October 2017 Posts: 2,371

Thanks for the prompt on inversion of normals with meshes, I mentioned this in a recent dialogue with @dave1707 on a 3D demo with Craft. I noticed it whilst building a skybox.

With respect to your above code - is this intended to be within project conversion ? So you add the new tab with a few mods and it runs with the in-house conversion of the mesh to an in-house obj model? If so very neat !!!

Would this allow you to write to an .obj model file from a built up mesh?

On the classic Roller Coaster demo a revision as a mesh to update to the latest Codea spec (didn’t you write your own Vec3() code?) and the equivalent Craft demo would be great. Good examples are always welcome.

On 3D objects only having one face is that true, I always wondered if it was lack of light source inside models?

Craft is fantastic and will take me a little time to digest properly. But, meshes appear more flexible if a little bit harder to create.

Can meshes and models(Craft) be used together or do the Craft scenes use the mesh and overwrite it?

• Posts: 2,371

Just thinking - your code may allow us to build our own model conversion utils. There is already a Codea ply loader.

Posts: 643
• Posts: 509

@Simeon I think there could be value in having something like the PseudoMesh class available, but I'm not sure if it's useful for it to be built in. I'm using it to convert old code over to Craft, but I'm not sure how much I'll use it for new code. At the moment, I tend to think in terms of meshes so my instincts are all centred on that. As I get more used to Craft, I'll probably be able to switch more easily between models and meshes.

I could put together a sample project with `PseudoMesh` as the non-Main tab, then it could be included via the project import feature.

Just in case my code above is of any use to you (or anyone else) ...

I hereby place the above `PseudoMesh` code in the public domain to the extent governable by law. Explicitly, I place it under the CC0.

Code that is placed in the public domain does not require attribution. However, if you have found it useful, the best way to say "Thank you" is to point others to it. So if you wish to acknowledge the source of the code, a link or bare URL text pointing to `http://loopspace.mathforge.org` would be nice.

I have a Craft version of the Roller Coaster almost ready - it currently pulls in some other code via `cmodule` so I just need to make it into a self-contained project.

@Bri_G Yes, the intention is to make it easy to convert from meshes to models. The above is not enough, but certainly helps me a lot. I have quite a lot of legacy code which I'd like to be able to use with Craft, for example my Mesh Extension Library adds lots of common shapes to the `mesh` object. Via the `PseudoMesh`, I can use it all with models as well without faffing around modifying the code.

Your mention of the `Vec3` code takes me back! Story of my life as regards Codea:

• October 2011 asking this question on the Apple Stack Exchange led me to Codify (as it was known then).

I don't remember what questions I emailed to Simeon but clearly the answer satisfied me that I'd be able to do what I wanted. Interesting that I was a bit wary about learning lua!

• December 2011 Write a shape explorer including my own font renderer, UI, touch handler, 3D capability ... then watch as over the years Codea implements just about all of those features itself.

I like to kid myself that some of what I did with Codea in the early days inspired Simeon and co to implement stuff natively.

Codea is simply amazing and made programming actually joyful rather than just how to get some task done. From fonts to meshes to shaders and now craft, it's been a bit of a roller coaster journey itself!

Sorry ... I'm waxing lyrical. @Bri_G got me in a nostalgic mood. I'd better stop before I start going on about the early days with Bortels and Fred and Nat ...

• Posts: 2,371

@LoopSpace
Nostalgia - I assume Nat is @Ignatz, there are many names you could add but I’m still using @Jmv38 code for spherical mesh generation, for my skybox. Codea is making great strides but some of the older coders code is still solid!!!

• Posts: 509

@Bri_G No, Nat is not Ignatz. Ignatz joined in 2013. I'm talking about 2011 - the really old days. Back then, we didn't even have `text`, let alone meshes and shaders. Not even 3D - we had to write our own 3D-to-2D projection stuff back in those days. I regard Ignatz as a youngster in Codea terms!

But now you've really got me going. I've started on "Back in my day ... "!

Posts: 5,708

@LoopSpace your font renderer is exactly what made me implement native text rendering! I got to see how valuable it was and so felt motivated to include it. A lot of Codea's features get implemented like that.

• Posts: 645

@LoopSpace in the comments of your sphere mesh, you hint that it could be possible (but not yet implemented) to smooth a faceted sphere. In order to keep the fps high i use a low number of facets. Would a smoothed sphere with low number of facets still be ‘fast’? If so, could you be persuaded to implement the smooth sphere option? Of course the correct texturing of the sphere should be retained. The in-built craft spheres do not seem to apply the texture correctly.

• Posts: 509

Hi @piinthesky,

Simply put: don't believe everything you read! Looking through the code, that has been implemented (if you trace through the code at https://github.com/loopspace/Codea-Library-Graphics/blob/master/MeshExt.lua then line 1318 is the key line: `f` is what the `faceted` option has become and this defines the normal accordingly.

Faceting vs smoothing is all about the normals and has no effect on where the texture coordinates are (though it will affect the shading). I'm pretty sure that my texture coordinates are in the right place.

The default appears to be smooth, so if you have a sphere with my code it ought to be smooth. Let me know if not.

• Posts: 645

@LoopSpace you are right i should not believe what i read! i set faceted true and i can clearly see the difference. Interestingly with faceted true my texture misbehaves-it seems to rotate around the sphere as i view the sphere from different angles (works ok for the default faceted false).

i was hoping to get the ‘profile’ of the sphere more circular but i guess only increasing the number of facets can help with that (but too slow).

Setting up my 2000 craft/pseudomesh spheres take a lot of time. Can you think of a clever way to speed that up?

• Mod
edited December 2018 Posts: 9,480

@piinthesky Are you trying to draw 2000 craft spheres with a texture on them. How long does it take you to draw your 2000 spheres.

• Posts: 645

@dave1707 drawing is not so bad (fps around 20-30ish with everything else going on). Setting up takes 14.2secs for 1800 craft spheres on ipad pro 12.9’’. It was slow enough i introduced a coroutine to display an animation during the setup (coroutine was disabled for the timing quoted above).

• Mod
edited December 2018 Posts: 9,480

@piinthesky I’m working on something right now that draws 2000 level 2 craft spheres (smooth) with textures at 22 fps on my iPad Air. It takes approx 7 seconds to create them. I’m tidying up the code now. I’ll try it on my iPad Pro and see what the times are.

• Mod
Posts: 9,480

@piinthesky On my iPad Pro it takes 3 seconds to load and runs at 54 fps.

• Posts: 645

@dave1707 mine are craft models made via the pseudomesh with number=6. i am going to try copying the vertices and normals from the first sphere and use in the subsequent spheres. this should avoid a lot of calculations.

• Mod
Posts: 9,480

@piinthesky That’s how I got mine to run faster. I created all the sphere tables first and then use them when I created the other spheres. I looked at the code from the link above, but when I saw it was 1609 lines, I closed it. Too many lines for me to look at.

• Posts: 645

@dave1707 it worked, down from 14 secs to 1 sec -great!

• Posts: 509

@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.

• Posts: 645

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

• Posts: 509

@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.

Posts: 643

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

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

• Mod
Posts: 9,480

@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.

• Posts: 2,371
@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.
Posts: 643

@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
``````
• Posts: 645

@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....

Posts: 643

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

• Posts: 2,371
@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.
• Posts: 645

@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
else
end
end)

parameter.boolean("DrawPointCloud", true)

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
``````
• Posts: 645

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

• Posts: 645

@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?

Posts: 5,708

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

Posts: 643

@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.

• Posts: 645

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

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

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.

image.jpeg 21.6K
Posts: 5,708

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

• edited January 2019 Posts: 645

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!

• Posts: 645
@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?
• Posts: 509

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

Can you post a small example?

• edited December 2019 Posts: 645

@LoopSpace here is my test code. I am trying to make a spotlight beam effect using a 3d cone. Need to add dependencies on your PseudoMesh class and the orbitViewer class (in. Examples). You will see the cone disappears at the same viewer angles for both the invertedNormals and non-inverted normals? Set useTransparency to true get the effect of the light fading with distance (sort of).

``````-- Test spotlight beam using cone

-- Use this function to perform your initial setup
function setup()

-- Create a new craft scene
scene = craft.scene()

--orbital viewer
orv=scene.camera:get(OrbitViewer)

--texture for cone for transparency
useTransparency=false
if useTransparency then
coneTexture=image(255,255)
setContext(coneTexture)
for i=1,255 do
for j=1,255 do
mycol=color(46, 218, 240, j)
coneTexture:set(i,j,mycol )
end
end
setContext()
end

coneHeight=1
coneBase=1

local coneMesh = PseudoMesh()
ends=0,
axis=vec3(0,1,0),
height=coneHeight,
centre=vec3(0,-coneHeight/2,0),
size=30,   --number of facets
})
--    coneMesh:invertNormals()
coneModel= coneMesh:toModel()

--
local coneMesh2 = PseudoMesh()
ends=0,
axis=vec3(0,1,0),
height=coneHeight,
centre=vec3(0,-coneHeight/2,0),
size=30,   --number of facets
})
coneMesh2:invertNormals()
coneModel2= coneMesh2:toModel()

cone1=scene:entity()
cone1.model =coneModel
cone1.scale=vec3(1,1,1)*50
cone1.material = craft.material("Materials:Standard")
if useTransparency then
cone1.material.map=coneTexture
cone1.material.diffuse=color(255, 0, 37, 255)
cone1.material.opacity=0.8
cone1.material.blendMode=NORMAL
end

cone2=scene:entity()
cone2.model =coneModel2
cone2.scale=vec3(1,1,1)*50
cone2.material = craft.material("Materials:Standard")
cone2.position=vec3(0,100,0)
if useTransparency then
cone2.material.map=coneTexture
cone2.material.diffuse=color(255, 0, 37, 255)
cone2.material.opacity=0.8
cone2.material.blendMode=NORMAL
end
--]]

end

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

function draw()
update(DeltaTime)
scene:draw()
end

function touched(touch)
orv:touched(touch)
end
``````
• Posts: 509

@piinthesky The problem is that you are using `addCylinder` to add a cone. Since `addCylinder` is designed for cylinders, it expects there to be a circle at either end and so all of the normals are calculated using how each triangle relates to the circle at its end. By making the ending radius 0, you are scupperring this calculation. So many of your normals are 0 (or possibly NaN).

The simplest solution is to make the end radius small but non-zero. I get a reasonable looking cone with end radius 0.1, but 0.01 also works.

There is an `addCone` method, but that is more general and needs more input. What this does is take a set of points, thought of as a sample of points along a path, and constructs what is known as the "topological cone" on that set of points. This involves connecting each given point to an apex (which must also be specified). As it is more general, you have to construct the points explicitly.

• Posts: 645

@LoopSpace Ahha, eureka! Yes, setting the end radius to a non-zero small value does the trick. By drawing two cones at the same location one with 'normal' normals, the other with 'inverted' normals and setting useTransparency=true gives pretty much the effect i was looking for. Thanks.

Currently, the transparency of the texture increases as function of distance from the apex. I would also like that the transparency increases as a function of distance from the cone axis i.e. soften the 'edges' of the light beam cone-can you think of a way to do that?

• Mod
Posts: 9,480

Thought I’d try my hand at making a transparent cone that moves thru a cube of spheres. I took one of my tube programs and modified it to make a cone. When you run this, it’s not a true cone just to make it easier to see what it looks like as you rotate the cubed spheres. To see a full cone, comment out the line conePoint=2 at the start of the code so that conePoint has a value of 1000.

``````displayMode(FULLSCREEN)

function setup()
conePoint=1000
conePoint=2
assert(OrbitViewer, "Please include Cameras (not Camera) as a dependency")
scene = craft.scene()
v.camera.farPlane=3000
v.rx,v.ry=10,-45
cone(vec3(400,0,0),vec3(0,0,0),200,40)
for x=-5,5 do   -- create cube of spheres
for y=-5,5 do
for z=-5,5 do
createSphere(vec3(x*60,y*60,z*60))
end
end
end
x,y,z=400,100,0 -- cone starting position
end

function draw()
update(DeltaTime)
scene:draw()
end

function update(dt)
scene:update(dt)
x=x-.5  -- move cone thru spheres
cn.position=vec3(x,y,z) -- change cone position
end

function cone(p1,p2,dia,sides)
local pos,ind,nor,col={},{},{},{}
local rp=vec3(100,100,100)
local v1=rp-p1
local r1=v1:cross(p2-p1)
local s1=r1:cross(p2-p1)
local n
r1,s1=r1:normalize(),s1:normalize()
for a=0,719,360/sides do
n=n*dia
if a>359 then
table.insert(pos,n/conePoint + p2)    -- add p2 to last loop
else
table.insert(pos,n + p1)    -- add p1 to loop
end
table.insert(nor,n)
end
local o,p={1,2,3,4,5,6,3,2,1,6,5,4},{}
for z=1,#pos-sides do
p[1],p[2],p[3],p[4],p[5],p[6]=z,z+1,z+sides+1,z,z+sides+1,z+sides
if z%sides==0 then
p[2]=z-sides+1
p[3]=z+1
p[5]=z+1
end
for t=1,12 do
table.insert(ind,p[o[t]])
end
end
for z=1,#pos do
table.insert(col,color(255))
end
cn=scene:entity()
cn.model = craft.model()
cn.model.positions=pos
cn.model.indices=ind
cn.model.colors=col
cn.model.normals=nor
cn.material=craft.material("Materials:Basic")
cn.material.blendMode = NORMAL
cn.material.opacity=.5
end

function createSphere(p)
local s=scene:entity()
s.position=vec3(p.x,p.y,p.z)
s.model = craft.model.icosphere(8,3)
s.material = craft.material("Materials:Specular")
s.material.diffuse=color(255,0,0)
end
``````
• edited December 2019 Posts: 645

@dave1707, thanks that is interesting-i always thought that with craft models only either the inner or outer surfaces can be visible, but here both are visible! @LoopSpace why then are the PseudoMesh models only visible on one of the surfaces?

@dave1707 i tried to use my coneTexture (see the code i uploaded earlier) on your implementation of the cone, but it does not seem to work? Using coneTexture was a way to make the intensity of the 'spot light' fade as a function of distance from the apex.

• Mod
Posts: 9,480

@piinthesky Not sure why texture isn’t working. In other code, I use something like cn.material.map=img and I get the img texture. Maybe because I’m not using a built in model or maybe there’s something else that needs to be set. I don’t fully understand everything that needs to be set.

• Mod
Posts: 9,480

@piinthesky Here’s another version where a map can be used. I created a white gradient image to use so the cone gets darker the farther away from the cube. I don’t know if this is any better for you.

``````displayMode(FULLSCREEN)

function setup()
img=image(256,256)  -- create gradiant texture image
setContext(img)
for x=0,256 do
for y=0,256 do
img:set(x,y,x,x,x)
end
end

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)
v.camera.farPlane=10000
pos={}
for z=0,360,20 do
table.insert(pos,vec3(x,y,800))
table.insert(pos,vec3(x,y,25))
end
for z=1,#pos-2,2 do
p1=pos[z]
p2=pos[z+1]
p3=pos[z+3]
p4=pos[z+2]
createTile(p1,p2,p3,p4)
end
z=#pos-1
p1=pos[z]
p2=pos[z+1]
p3=pos[2]
p4=pos[1]
createTile(p1,p2,p3,p4)
createCube(vec3(0,0,0))
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,255,255,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.blendMode = NORMAL
pt.material.opacity=.8
pt.material.map=img
end

function createCube(p)
local s=scene:entity()
s.position=vec3(p.x,p.y,p.z)
s.model = craft.model.cube(vec3(50,50,50))
s.material = craft.material("Materials:Specular")
s.material.diffuse=color(255,0,0)
end
``````
• Posts: 2,371

@piinthesky @dave1707 - just looking at this from an external point of view the cone seems to look artificial - that is it looks like a solid object. There was a post by @ignatz where he was building a 2d game where he made a flaming torch for mazes which produced an in beam high colour out of beam graduated darker effect - link below. I think you may need a shader for this where all in beam objects are shown in true colour fading offset towards the perimeter rather than building an object.

https://codea.io/talk/discussion/5614/2d-sidescrolling-toolkit#latest

• Posts: 509

@piinthesky The model in @dave1707 's code is visible from both sides because each triangle is included twice, once with the vertices clockwise and once anticlockwise. This makes it visible from both sides. You could achieve the same effect with my code by adding a second copy of the cone with inverted normals. Speaking of which, the normals in @dave1707 's code aren't quite right - they don't take into account the slant of the cone sides.

As to the transparency, I have to admit that I'm not really sure what you are trying to accomplish overall so can't advise on the best solution, but distance from the cone axis is proportional to distance from the apex so if you can fade appropriately from the apex then you'll be fine. If this is simulating a light cone, then it should fade with the inverse square of the distance to the apex. But changes in transparency don't always look the same to the eye as they do in the code so you'd just have to experiment.

• Posts: 2,371
@piinthesky - just picking up on my earlier point. The image you produce depends on the perspective with regard to viewing point. Do you need a sideways view of a light source moving through the environment or are you needing a viewpoint behind the light source which moves with the camera?

The latter could be simulated by a graduated screen just in front of the camera i.e. make the background darker with the centre focus brighter.

One thing you need to do is brighten the image which is at the end of the cone i.e.the broad end (target for the beam), if you are viewing from the side.
• edited December 2019 Posts: 2,371

@piinthesky - just watched your video again and note that the craft you use is not shaded so it looks like you don’t have a light source in the project although you have produced a lot of interesting light effects.

How have you generated your ‘world’ ? Are you using Craft, if you are then you could add light sources to shade and illuminate to produce the effect you need.