Difference between revisions of "Libs3D Mesh"

From GiderosMobile
Line 161: Line 161:
 
The principles are the same as flat 3D but with an extra axis to deal with. Let's introduce Texturing as well.
 
The principles are the same as flat 3D but with an extra axis to deal with. Let's introduce Texturing as well.
  
The raw:
+
==== '''The raw''' ====
 
<syntaxhighlight lang="lua">
 
<syntaxhighlight lang="lua">
 
application:setBackgroundColor(0x323232)
 
application:setBackgroundColor(0x323232)
Line 211: Line 211:
 
plane3d:setRotation(plane3d:getRotation()+1.3)
 
plane3d:setRotation(plane3d:getRotation()+1.3)
 
end)
 
end)
 +
</syntaxhighlight>
 +
 +
==== '''The Class''' ====
 +
Almost the same as above but we are getting real here, aren't we?
 +
<syntaxhighlight lang="lua">
 +
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
 
</syntaxhighlight>
 
</syntaxhighlight>
  

Revision as of 02:31, 25 January 2026

Supported platforms: Platform android.pngPlatform ios.pngPlatform mac.pngPlatform pc.pngPlatform html5.pngPlatform winrt.pngPlatform win32.pngPlatform linux.png

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)

3d triangle.png

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

Libs3D