@Bri_G The more I play with this, the weirder it gets. Here are 5 icospheres. Move the “lines” slider to show the lines. Not all of the lines are shown which I expect because there’s more than 32,768 lines. But here’s where the odd stuff starts to happen. Move the “slow” slider so it starts to draw the lines for each of the icospheres slowly. Everything goes OK until the running total reaches 32,768. After that, as the lines of the left icospheres are being drawn, the lines of the right icosphere are now un-drawing. That will continue until all the lines of the left icospheres are drawn. After that the count keeps increasing for the rightmost icosphere, but since we’re above 32,768 nothing is drawn anymore. Not sure about the un-drawing.
viewer.mode=STANDARD
function setup()
font("Courier")
parameter.watch("fps")
textMode(CORNER)
totalLines=0
fill(255)
parameter.boolean("lines",false)
parameter.boolean("slow",false)
sTab={}
assert(OrbitViewer, "Please include Cameras as a dependency")
assert(icoSphere, "Please include IcoCreate as a dependency")
scene = craft.scene()
scene.ambientColor=color(255)
v=scene.camera:add(OrbitViewer, vec3(0,0,0), 150, 0, 3000)
v.ry=180
image=readImage(asset.builtin.Surfaces.Basic_Bricks_AO)
table.insert(sTab,icoSphere(vec3(-50,0,0),10,4,false,false,1,image))
table.insert(sTab,icoSphere(vec3(-25,0,0),10,4,false,false,1,image))
table.insert(sTab,icoSphere(vec3(0,0,0),10,3,false,false,1,image))
table.insert(sTab,icoSphere(vec3(25,0,0),10,1,false,false,1,image))
table.insert(sTab,icoSphere(vec3(50,0,0),10,5,false,false,1,image))
tl=true
for a,b in pairs(sTab) do
totalLines=totalLines+#b.model.indices
end
end
function draw()
fps=1//DeltaTime
update(DeltaTime)
scene:draw()
tl=0
for a,b in pairs(sTab) do
if lines then
b.material.opacity=0
drawLines(b)
else
b.material.opacity=1
b.nbr=0
end
str=string.format("Level %2d %8d %8d",b.level,#b.model.positions,b.nbr)
text(str,100,HEIGHT-a*40-50)
tl=tl+b.nbr
end
str=string.format("Total %10d %10d",totalLines,tl)
text(str,100,HEIGHT-20)
end
function update(dt)
scene:update(dt)
for a,b in pairs(sTab) do
b.rotation = quat.eulerAngles(-90,0,0)
end
end
function drawLines(s)
s.material.blendMode=NORMAL
local sd=scene.debug
local pTab=s.model.positions
local iTab=s.model.indices
if not slow then
for z=1,#s.model.indices,3 do
local p1=pTab[iTab[z]]+s.position
local p2=pTab[iTab[z+1]]+s.position
local p3=pTab[iTab[z+2]]+s.position
sd:line(p1,p2,color(255))
sd:line(p1,p3,color(255))
sd:line(p2,p3,color(255))
end
else
if s.nbr<=#s.model.indices-3 then
s.nbr=s.nbr+3
end
for z=1,s.nbr,3 do
local p1=pTab[iTab[z]]+s.position
local p2=pTab[iTab[z+1]]+s.position
local p3=pTab[iTab[z+2]]+s.position
sd:line(p1,p2,color(255))
sd:line(p1,p3,color(255))
sd:line(p2,p3,color(255))
end
end
end
function icoSphere(pos,size,level,flat,inside,material,image)
local s=scene:entity()
s.position=pos
s.model=craft.model.icosphere(size,level,flat) -- create icosphere
if material==1 or material>3 or material==nil then
s.material=craft.material(asset.builtin.Materials.Basic)
elseif material==2 then
s.material=craft.material(asset.builtin.Materials.Standard)
else
s.material=craft.material(asset.builtin.Materials.Specular)
end
if image~=nil then
icoTexture(s,inside,image)
else
for z=1,#s.model.colors do
s.model:color(z,color(math.random(255),math.random(255),math.random(255)))
end
end
s.nbr=0
s.level=level
return s
end
function icoTexture(sph,inside,img)
local seam=0
local ax,bx,cx,ay,by,cy,c,lat,lon
local posTab={}
local pTab,cTab,nTab,llTab,uvTab,colTab,norTab,iTab={},{},{},{},{},{},{},{}
local deg=math.deg
local asin=math.asin
local atan2=math.atan2
sph.material.map=img
-- create tables for rounded icospheres
if not flat then
iTab=sph.model.indices
pTab=sph.model.positions
cTab=sph.model.colors
nTab=sph.model.normals
for a,b in pairs(iTab) do
posTab[a]=pTab[b]
colTab[a]=cTab[b]
norTab[a]=nTab[b]
iTab[a]=a
end
end
-- convert sphere positions to latitude and longitude
for a,b in pairs(posTab) do
c=b:normalize()
lat=deg(asin(c.z))+90
lon=deg(atan2(c.y,c.x))
llTab[a]=vec2(lon,lat) -- save lon, lat in table
if lon//1==-149 then -- get exact value of seam
seam=lon
end
end
-- shift points on the left side of the seam to the right side
for a,b in pairs(llTab) do
b.x=b.x-seam
if b.x<-.01 then
b.x=b.x+360
end
end
-- shift individual points of triangle if needed
for z=1,#llTab,3 do
ax,ay=llTab[z].x,llTab[z].y
bx,by=llTab[z+1].x,llTab[z+1].y
cx,cy=llTab[z+2].x,llTab[z+2].y
if ax>250 or bx>250 or cx>250 then
if ax<.01 then
ax=360
end
if bx<.01 then
bx=360
end
if cx<.01 then
cx=360
end
end
if ay==0 or ay==180 then
ax=(bx+cx)*.5
elseif by==0 or by==180 then
bx=(ax+cx)*.5
elseif cy==0 or cy==180 then
cx=(ax+bx)*.5
end
-- create uv table
uvTab[z]=vec2(ax/360,ay/180)
uvTab[z+1]=vec2(bx/360,by/180)
uvTab[z+2]=vec2(cx/360,cy/180)
end
-- reset tables
sph.model.uvs=uvTab
-- flat shows the triangles that make the sphere
if not flat then
sph.model.indices=iTab
sph.model.positions=posTab
sph.model.colors=colTab
sph.model.normals=norTab
end
--update indices table for inside view
if inside then
iTab=sph.model.indices
for z=#sph.model.indices,1,-1 do
iTab[#iTab+1]=iTab[z]
end
sph.model.indices=iTab
end
end