Difference between revisions of "Libs3D Mesh"
(→Cubez) |
|||
| Line 347: | Line 347: | ||
end | end | ||
</syntaxhighlight> | </syntaxhighlight> | ||
| + | |||
| + | === SphereZ === | ||
| + | Doing 3D manually can quickly get ugly (unless you use AI 😉). Show me your spherez! | ||
| + | <syntaxhighlight lang="lua"> | ||
| + | Sphere = Core.class(Mesh) | ||
| + | |||
| + | function Sphere:init(steps,radius) | ||
| + | local va, ia = {}, {} | ||
| + | local rs = (2*math.pi)/steps | ||
| + | local idx, ni = 4, 1 | ||
| + | -- Vertices | ||
| + | va[1]=0 va[2]=radius va[3]=0 | ||
| + | for iy = 1, (steps//2)-1 do | ||
| + | local y = math.cos(iy*rs)*radius | ||
| + | local r = math.sin(iy*rs)*radius | ||
| + | -- local y = math.cos(iy*rs)*radius -- test me | ||
| + | -- local r = math.cos(iy*rs)*radius -- test me | ||
| + | for ix = 0, steps do | ||
| + | local x = r*math.cos(ix*rs) | ||
| + | local z = r*math.sin(ix*rs) | ||
| + | va[idx]=x idx+=1 | ||
| + | va[idx]=y idx+=1 | ||
| + | va[idx]=z idx+=1 | ||
| + | end | ||
| + | end | ||
| + | va[idx]=0 va[idx+1]=-radius va[idx+2]=0 | ||
| + | local lvi = idx//3+1 | ||
| + | -- Indices | ||
| + | -- a) top and bottom fans | ||
| + | for i = 1, steps do | ||
| + | ia[ni]=1 ni+=1 ia[ni]=i+1 ni+=1 ia[ni]=i+2 ni+=1 | ||
| + | ia[ni]=lvi ni+=1 ia[ni]=lvi-i ni+=1 ia[ni]=lvi-i-1 ni+=1 | ||
| + | end | ||
| + | -- b) quads | ||
| + | for iy = 1,(steps//2)-2 do | ||
| + | local b = 1+(steps+1)*(iy-1) | ||
| + | for ix = 1, steps do | ||
| + | ia[ni]=b+ix ni+=1 ia[ni]=b+ix+1 ni+=1 ia[ni]=b+ix+steps+1 ni+=1 | ||
| + | ia[ni]=b+ix+steps+1 ni+=1 ia[ni]=b+ix+1 ni+=1 ia[ni]=b+ix+steps+2 ni+=1 | ||
| + | end | ||
| + | end | ||
| + | self:setVertexArray(va) | ||
| + | self:setIndexArray(ia) | ||
| + | self._va=va self._ia=ia | ||
| + | self._steps=steps | ||
| + | end | ||
| + | |||
| + | function Sphere:mapTexture(texture,sw,sh) | ||
| + | local tw, th = texture:getWidth()*(sw or 1), texture:getHeight()*(sh or 1) | ||
| + | local va = {} | ||
| + | local i = 3 | ||
| + | -- TexCoords | ||
| + | va[1]=tw/2 va[2]=0 | ||
| + | for iy = 1, (self._steps//2)-1 do | ||
| + | local y = th*(iy*2/self._steps) | ||
| + | for ix = 0, self._steps do | ||
| + | local x = tw*(ix/self._steps) | ||
| + | va[i]=x i+=1 | ||
| + | va[i]=y i+=1 | ||
| + | end | ||
| + | end | ||
| + | va[i]=tw/2 va[i+1]=th | ||
| + | self:setTextureCoordinateArray(va) | ||
| + | self:setTexture(texture) | ||
| + | end | ||
| + | |||
| + | function Sphere:mapColor(color,alpha) | ||
| + | for i = 1, #self._ia do | ||
| + | self:setColor(i, color, alpha or 1) | ||
| + | end | ||
| + | end | ||
| + | |||
| + | -- *************************************** | ||
| + | application:setBackgroundColor(0x323232) | ||
| + | |||
| + | -- configure the field of view for 3D projection | ||
| + | application:configureFrustum(45) -- (fov, farplane) | ||
| + | |||
| + | local spheres = { | ||
| + | Sphere.new(3*8, 8*8), -- (steps,radius) | ||
| + | Sphere.new(1*8, 4*8), -- (steps,radius) | ||
| + | Sphere.new(2*8, 6*8), -- (steps,radius) | ||
| + | } | ||
| + | |||
| + | local tex = Texture.new("gfx/Aurichalcite Deposit.jpg", false, { wrap=Texture.REPEAT, } ) | ||
| + | for i = 1, #spheres do | ||
| + | spheres[i]:mapTexture(tex, 0.2*8, 0.2*8) -- texture,sw,sh | ||
| + | spheres[i]:setPosition(i*8*16, 10*16, -1*16) | ||
| + | stage:addChild(spheres[i]) | ||
| + | -- Rotate | ||
| + | spheres[i]:addEventListener(Event.ENTER_FRAME,function(e) | ||
| + | spheres[i]:setRotationX(spheres[i]:getRotationX()+1) | ||
| + | spheres[i]:setRotation(spheres[i]:getRotation()+1.3) | ||
| + | end) | ||
| + | end | ||
| + | </syntaxhighlight> | ||
| + | |||
| + | == I am Out == | ||
| + | Here are your first steps with Gideros and 3D. | ||
| + | |||
| + | You are strongly encouraged to mess with the code to get a better understanding of all this ... ''mess''. | ||
| + | |||
| + | '''See ya'''! | ||
---- | ---- | ||
'''[[Libs3D]]''' | '''[[Libs3D]]''' | ||
{{GIDEROS IMPORTANT LINKS}} | {{GIDEROS IMPORTANT LINKS}} | ||
Revision as of 04:01, 25 January 2026
I am 3D
First and foremost, for 3D, we set our application as such. There are many ways to tell our application be 3D:
- application configureFrustum
- Matrix orthographicProjection
- Matrix perspectiveProjection
- Viewport setProjection
Let's see some of those making our first steps in Gideros 3D.
Flat 3D
A Triangle
As seen above, first we set our application 3D: configureFrustum.
The Mesh class is used to create and display custom constructed triangles (triangle meshes).
A triangle is:
- an array of 3 vertices with an x and y position: setVertexArray
- those 3 vertices connect to make a face (ClockWise): setIndexArray
- optionally coloring each vertex (color and alpha): setColorArray
The code:
application:setBackgroundColor(0x323232)
-- Configures the field of view (fov) and far clipping plane for 3D projection
application:configureFrustum(45, -100) -- (fov, farplane)
local mesh = Mesh.new()
mesh:setVertexArray(
50, 0, -- 1. vertex position
100, 100, -- 2. vertex position
0, 100 -- 3. vertex position
)
mesh:setIndexArray(
1,2,3 -- 1. triangle from 1, 2 and 3 vertex
)
mesh:setColorArray(
0xff0000,0.5, -- 1. vertex color and alpha
0x00ff00,0.7, -- 2. vertex color and alpha
0x0000ff,1.0 -- 3. vertex color and alpha
)
-- ok
mesh:setPosition(12*16, 8*16, -1*16)
stage:addChild(mesh)
mesh:addEventListener(Event.ENTER_FRAME, function(e)
mesh:setRotationX(mesh:getRotationX()+1)
mesh:setRotationY(mesh:getRotationY()+1)
mesh:setRotation(mesh:getRotation()+1)
end)
A Rectangle
Take the triangle code above, add one vertex and you have two triangles that make a rectangle.
application:setBackgroundColor(0x323232)
-- Configures the field of view (fov) and far clipping plane for 3D projection
application:configureFrustum(45, -100) -- (fov, farplane)
local mesh = Mesh.new()
mesh:setVertexArray(
0, 0, -- 1. vertex position
100, 0, -- 2. vertex position
100, 150, -- 3. vertex position
0, 150 -- -- 4. vertex position
)
mesh:setIndexArray(
1,2,3, -- 1. triangle from 1, 2 and 3 vertex
1,3,4 -- 2. triangle from 1, 3 and 4 vertex
)
mesh:setColorArray(
0xff0000,0.5, -- 1. vertex color and alpha
0x00ff00,0.7, -- 2. vertex color and alpha
0x0000ff,1.0, -- 3. vertex color and alpha
0xffff00,0 -- 4. vertex color and alpha
)
-- ok
mesh:setPosition(12*16, 8*16, -1*16)
stage:addChild(mesh)
mesh:addEventListener(Event.ENTER_FRAME, function(e)
mesh:setRotationX(mesh:getRotationX()+1)
mesh:setRotationY(mesh:getRotationY()+1)
mesh:setRotation(mesh:getRotation()+1)
end)
A Cube
In Gideros, a simple Sprite can be cube:
- we set the application 3D
- we create a local function to make the faces for our cube using Shape
- we add six faces (with appropriate rotation) to a parent Sprite
- and we are cube ;-)
application:setBackgroundColor(0x323232)
-- configure the field of view for 3D projection
application:configureFrustum(45) -- (fov, farplane)
-- create faces for a cube
local function face(color, rx, ry)
local s = Shape.new()
s:setFillStyle(Shape.SOLID, color, 0.7) -- translucent color
s:beginPath()
s:moveTo(-1,-1)
s:lineTo(-1,1)
s:lineTo(1,1)
s:lineTo(1,-1)
s:lineTo(-1,-1)
s:endPath()
-- orientation
s:setRotationX(rx)
s:setRotationY(ry)
-- offset position -1 along its local Z axis
s:setPosition(s:getMatrix():transformPoint(0, 0, -1))
return s
end
-- a cube with 6 faces
cube = Sprite.new()
cube:addChild(face(0xFF8080, 0,0)) -- color, rx, ry
cube:addChild(face(0xFFFF00, 90,0)) -- color, rx, ry
cube:addChild(face(0xFF00FF, -90,0)) -- color, rx, ry
cube:addChild(face(0x80FF80, 180,0)) -- color, rx, ry
cube:addChild(face(0x00FFFF, 0,90)) -- color, rx, ry
cube:addChild(face(0x8080FF, 0,-90)) -- color, rx, ry
-- enable depth sorting for translucency
cube:setAutoSort(true)
cube:setScale(2*16, 2*16, 2*16)
cube:setPosition(12*16, 8*16, 1*16)
stage:addChild(cube)
-- Rotate our cube
cube:addEventListener(Event.ENTER_FRAME,function(e)
cube:setRotationX(cube:getRotationX()+1)
cube:setRotation(cube:getRotation()+1.3)
end)
Let's get real
A 3D Plane
So far we managed to be 3D using only the x and y axes. Let's get real and add the z axis:
- Mesh.new(true)
Initializing a Mesh with true makes the mesh expect a Z coordinate in its vertex array. Now this is real 3D 😉.
The principles are the same as flat 3D but with an extra axis to deal with. Let's introduce Texturing as well.
The raw
application:setBackgroundColor(0x323232)
-- configure the field of view for 3D projection
application:configureFrustum(45) -- (fov, farplane)
local plane3d = Mesh.new(true) -- true = this mesh expects a Z coordinate in its vertex array
local w, h, d = 5*8, 1*8, 10*8 -- 3d plane dimensions
local va = { -- vertex array
-w,h,-d, -- 1. vertex position
w,h,-d, -- 2. vertex position
w,h,d, -- 3. vertex position
-w,h,d, -- 4. vertex position
-- -w,h-30,d, -- 4. vertex position, test another position
}
local ia = { -- index array
1,2,3, -- 1. triangle from 1, 2 and 3 vertex
1,3,4, -- 2. triangle from 1, 3 and 4 vertex
}
plane3d:setVertexArray(va)
plane3d:setIndexArray(ia)
-- texture it
local tex = Texture.new("gfx/Aurichalcite Deposit.jpg", false, { wrap=Texture.REPEAT, } )
local tw,th = tex:getWidth()*0.5, tex:getHeight()*1 -- 0.5 and 1 are the texture scale (uv)
plane3d:setTextureCoordinateArray {
0,0, -- 1. vertex texture coordinate
tw,0, -- 2. vertex texture coordinate
tw,th, -- 3. vertex texture coordinate
0,th, -- 4. vertex texture coordinate
}
plane3d:setTexture(tex)
-- why no color
plane3d:setColor(1, 0xffffff, 1)
plane3d:setColor(2, 0x5500ff, 1)
plane3d:setColor(3, 0x000000, 1)
plane3d:setColor(4, 0xaaff00, 1)
-- ok
plane3d:setPosition(12*16, 10*16, -1*16)
stage:addChild(plane3d)
-- rotate it
plane3d:addEventListener(Event.ENTER_FRAME,function(e)
plane3d:setRotationX(plane3d:getRotationX()+1)
plane3d:setRotation(plane3d:getRotation()+1.3)
end)
The Class
Almost the same as above but we are getting real here, aren't we?
local Plane3D = Core.class(Mesh)
function Plane3D:init(w,h,d)
w=w or 1 h=h or 1 d=d or 1
self._va = { -- vertex array
-w,h,-d,
w,h,-d,
w,h,d,
-w,h,d,
}
self._ia = { -- index array
1,2,3, 1,3,4,
}
self:setVertexArray(self._va)
self:setIndexArray(self._ia)
end
function Plane3D:mapTexture(texture,sw,sh)
local tw,th = texture:getWidth()*(sw or 1), texture:getHeight()*(sh or 1)
self:setTextureCoordinateArray {
0, 0,
tw, 0,
tw, th,
0, th,
}
self:setTexture(texture)
end
function Plane3D:mapColor(color,alpha)
for i = 1, #self._ia do
self:setColor(i, color, alpha or 1)
end
end
-- ***************************************
application:setBackgroundColor(0x323232)
-- configure the field of view for 3D projection
application:configureFrustum(45) -- (fov, farplane)
local planes3d = {
Plane3D.new(5*8, 1*8, 8*8), -- (w,h,d)
Plane3D.new(4*8, 1*8, 10*8), -- (w,h,d)
Plane3D.new(5*8, 1*8, 2*8), -- (w,h,d)
}
local tex = Texture.new("gfx/Aurichalcite Deposit.jpg", false, { wrap=Texture.REPEAT, } )
for i = 1, #planes3d do
planes3d[i]:mapTexture(tex, 0.5, 1) -- texture,sw,sh
planes3d[i]:mapColor(math.random(0xffffff), math.random()+0.1) -- color,alpha
planes3d[i]:setPosition(i*8*16, 10*16, -1*16)
stage:addChild(planes3d[i])
-- Rotate our 3D planes
planes3d[i]:addEventListener(Event.ENTER_FRAME,function(e)
planes3d[i]:setRotationX(planes3d[i]:getRotationX()+1)
planes3d[i]:setRotation(planes3d[i]:getRotation()+1.3)
end)
end
Cubez
Cuboid = Core.class(Mesh)
function Cuboid:init(w,h,d)
w=w or 1 h=h or 1 d=d or 1
self._va = { -- vertex array
-w,h,-d, w,h,-d, w,-h,-d, -w,-h,-d,
w,h,d, -w,h,d, -w,-h,d, w,-h,d,
-w,-h,-d, w,-h,-d, w,-h,d, -w,-h,d,
-w,h,d, w,h,d, w,h,-d, -w,h,-d,
-w,h,d, -w,h,-d, -w,-h,-d, -w,-h,d,
w,h,-d, w,h,d, w,-h,d, w,-h,-d,
}
self._ia = { -- index array
1,2,3,1,3,4,
5,6,7,5,7,8,
9,10,11,9,11,12,
13,14,15,13,15,16,
17,18,19,17,19,20,
21,22,23,21,23,24,
}
self:setVertexArray(self._va)
self:setIndexArray(self._ia)
end
function Cuboid:mapTexture(texture,sw,sh)
local tw, th = texture:getWidth()*(sw or 1), texture:getHeight()*(sh or 1)
self:setTextureCoordinateArray {
0,0,tw,0,tw,th,0,th,
0,0,tw,0,tw,th,0,th,
0,0,tw,0,tw,th,0,th,
0,0,tw,0,tw,th,0,th,
0,0,tw,0,tw,th,0,th,
0,0,tw,0,tw,th,0,th,
}
self:setTexture(texture)
end
function Cuboid:mapColor(color,alpha)
for i = 1, #self._ia do
self:setColor(i, color, alpha or 1)
end
end
-- ***************************************
application:setBackgroundColor(0x323232)
-- configure the field of view for 3D projection
application:configureFrustum(45) -- (fov, farplane)
local cubes = {
Cuboid.new(5*8, 10*8, 5*8), -- (w,h,d)
Cuboid.new(2*8, 2*8, 8*8), -- (w,h,d)
Cuboid.new(5*8, 5*8, 5*8), -- (w,h,d)
}
local tex = Texture.new("gfx/Aurichalcite Deposit.jpg", false, { wrap=Texture.REPEAT, } )
for i = 1, #cubes do
cubes[i]:mapTexture(tex, 0.5, 1) -- texture,sw,sh
cubes[i]:mapColor(math.random(0xffffff), 1) -- color,alpha
cubes[i]:setPosition(i*8*16, 10*16, -1*16)
stage:addChild(cubes[i])
-- Rotate
cubes[i]:addEventListener(Event.ENTER_FRAME,function(e)
cubes[i]:setRotationX(cubes[i]:getRotationX()+1)
cubes[i]:setRotation(cubes[i]:getRotation()+1.3)
end)
end
SphereZ
Doing 3D manually can quickly get ugly (unless you use AI 😉). Show me your spherez!
Sphere = Core.class(Mesh)
function Sphere:init(steps,radius)
local va, ia = {}, {}
local rs = (2*math.pi)/steps
local idx, ni = 4, 1
-- Vertices
va[1]=0 va[2]=radius va[3]=0
for iy = 1, (steps//2)-1 do
local y = math.cos(iy*rs)*radius
local r = math.sin(iy*rs)*radius
-- local y = math.cos(iy*rs)*radius -- test me
-- local r = math.cos(iy*rs)*radius -- test me
for ix = 0, steps do
local x = r*math.cos(ix*rs)
local z = r*math.sin(ix*rs)
va[idx]=x idx+=1
va[idx]=y idx+=1
va[idx]=z idx+=1
end
end
va[idx]=0 va[idx+1]=-radius va[idx+2]=0
local lvi = idx//3+1
-- Indices
-- a) top and bottom fans
for i = 1, steps do
ia[ni]=1 ni+=1 ia[ni]=i+1 ni+=1 ia[ni]=i+2 ni+=1
ia[ni]=lvi ni+=1 ia[ni]=lvi-i ni+=1 ia[ni]=lvi-i-1 ni+=1
end
-- b) quads
for iy = 1,(steps//2)-2 do
local b = 1+(steps+1)*(iy-1)
for ix = 1, steps do
ia[ni]=b+ix ni+=1 ia[ni]=b+ix+1 ni+=1 ia[ni]=b+ix+steps+1 ni+=1
ia[ni]=b+ix+steps+1 ni+=1 ia[ni]=b+ix+1 ni+=1 ia[ni]=b+ix+steps+2 ni+=1
end
end
self:setVertexArray(va)
self:setIndexArray(ia)
self._va=va self._ia=ia
self._steps=steps
end
function Sphere:mapTexture(texture,sw,sh)
local tw, th = texture:getWidth()*(sw or 1), texture:getHeight()*(sh or 1)
local va = {}
local i = 3
-- TexCoords
va[1]=tw/2 va[2]=0
for iy = 1, (self._steps//2)-1 do
local y = th*(iy*2/self._steps)
for ix = 0, self._steps do
local x = tw*(ix/self._steps)
va[i]=x i+=1
va[i]=y i+=1
end
end
va[i]=tw/2 va[i+1]=th
self:setTextureCoordinateArray(va)
self:setTexture(texture)
end
function Sphere:mapColor(color,alpha)
for i = 1, #self._ia do
self:setColor(i, color, alpha or 1)
end
end
-- ***************************************
application:setBackgroundColor(0x323232)
-- configure the field of view for 3D projection
application:configureFrustum(45) -- (fov, farplane)
local spheres = {
Sphere.new(3*8, 8*8), -- (steps,radius)
Sphere.new(1*8, 4*8), -- (steps,radius)
Sphere.new(2*8, 6*8), -- (steps,radius)
}
local tex = Texture.new("gfx/Aurichalcite Deposit.jpg", false, { wrap=Texture.REPEAT, } )
for i = 1, #spheres do
spheres[i]:mapTexture(tex, 0.2*8, 0.2*8) -- texture,sw,sh
spheres[i]:setPosition(i*8*16, 10*16, -1*16)
stage:addChild(spheres[i])
-- Rotate
spheres[i]:addEventListener(Event.ENTER_FRAME,function(e)
spheres[i]:setRotationX(spheres[i]:getRotationX()+1)
spheres[i]:setRotation(spheres[i]:getRotation()+1.3)
end)
end
I am Out
Here are your first steps with Gideros and 3D.
You are strongly encouraged to mess with the code to get a better understanding of all this ... mess.
See ya!

