Groverburger's 3D Engine (g3d) v1.5.2 Release
Re: Groverburger's 3D Engine (g3d) v1.5.2 Release
It's working with anim9?
- Jasoco
- Inner party member
- Posts: 3726
- Joined: Mon Jun 22, 2009 9:35 am
- Location: Pennsylvania, USA
- Contact:
Re: Groverburger's 3D Engine (g3d) v1.5.2 Release
It's amazing what you can do with shaders when you spend a little time Googling and experimenting.
I do wish I could do true lighting though. With shadows and such. Right now it's pretty simplistic. A mixture of calculated point lights and pre-baked lighting. Also every texture can have an associated "bright pixel" atlas for textures that need to have parts that are always full brightness. (For example, the green lights on the doors, the fluorescent lights in the last screenshot and the soda machine facades are all bright pixels.)
Also, everything is pretty much coded tables instead of .obj files. I haven't been able to figure out how to use 3D modeling software and the ones that I like don't export the files with the proper axis "up" that g3d expects. So I find it easier to just construct everything from triangles manually. I feel that uses a lot of memory though. I had a lot of memory problems with some of my earlier experiments where I was trying to make too big of a world with way too many polygons. So I borrowed the method used by Leadhaul for building my maps and creating my sprites.
I do wish I could do true lighting though. With shadows and such. Right now it's pretty simplistic. A mixture of calculated point lights and pre-baked lighting. Also every texture can have an associated "bright pixel" atlas for textures that need to have parts that are always full brightness. (For example, the green lights on the doors, the fluorescent lights in the last screenshot and the soda machine facades are all bright pixels.)
Also, everything is pretty much coded tables instead of .obj files. I haven't been able to figure out how to use 3D modeling software and the ones that I like don't export the files with the proper axis "up" that g3d expects. So I find it easier to just construct everything from triangles manually. I feel that uses a lot of memory though. I had a lot of memory problems with some of my earlier experiments where I was trying to make too big of a world with way too many polygons. So I borrowed the method used by Leadhaul for building my maps and creating my sprites.
Re: Groverburger's 3D Engine (g3d) v1.5.2 Release
I made a pull request on the g3d repo so that the objloader.lua script accepts models with non-triangulated faces, here is my version if you want to use it now:
It works very well for all the models I have tested, tell me what you think
Code: Select all
-- written by groverbuger for g3d
-- september 2021
-- MIT license
----------------------------------------------------------------------------------------------------
-- simple obj loader
----------------------------------------------------------------------------------------------------
-- give path of file
-- returns a lua table representation
return function (path, uFlip, vFlip)
local positions, uvs, normals = {}, {}, {}
local result = {}
-- go line by line through the file
for line in love.filesystem.lines(path) do
local words = {}
-- split the line into words
for word in line:gmatch "([^%s]+)" do
table.insert(words, word)
end
local firstWord = words[1]
if firstWord == "v" then
-- if the first word in this line is a "v", then this defines a vertex's position
table.insert(positions, {tonumber(words[2]), tonumber(words[3]), tonumber(words[4])})
elseif firstWord == "vt" then
-- if the first word in this line is a "vt", then this defines a texture coordinate
local u, v = tonumber(words[2]), tonumber(words[3])
-- optionally flip these texture coordinates
if uFlip then u = 1 - u end
if vFlip then v = 1 - v end
table.insert(uvs, {u, v})
elseif firstWord == "vn" then
-- if the first word in this line is a "vn", then this defines a vertex normal
table.insert(normals, {tonumber(words[2]), tonumber(words[3]), tonumber(words[4])})
elseif firstWord == "f" then
-- if the first word in this line is a "f", then this is a face
-- a face takes three point definitions
-- the arguments a point definition takes are vertex, vertex texture, vertex normal in that order
local vertices = {}
for i = 2, #words do
local v, vt, vn = words[i]:match "(%d*)/(%d*)/(%d*)"
v, vt, vn = tonumber(v), tonumber(vt), tonumber(vn)
table.insert(vertices, {
v and positions[v][1] or 0,
v and positions[v][2] or 0,
v and positions[v][3] or 0,
vt and uvs[vt][1] or 0,
vt and uvs[vt][2] or 0,
vn and normals[vn][1] or 0,
vn and normals[vn][2] or 0,
vn and normals[vn][3] or 0,
})
end
-- triangulate the face if it's not already a triangle
if #vertices > 3 then
-- choose a central vertex
local centralVertex = vertices[1]
-- connect the central vertex to each of the other vertices to create triangles
for i = 2, #vertices - 1 do
table.insert(result, centralVertex)
table.insert(result, vertices[i])
table.insert(result, vertices[i + 1])
end
else
for i = 1, #vertices do
table.insert(result, vertices[i])
end
end
end
end
return result
end
Re: Groverburger's 3D Engine (g3d) v1.5.2 Release
Can you draw a 3D line in this engine? I tried it by defining a vertex array as a 3D line with two points.
This is the desired format
local vertexFormatLines={
{"VertexPosition", "float", 3},
{"VertexColor", "byte", 4},
}
local vertices={{0,0,0,1,1,1,1},{0,0,100,1,1,1,1}}
model.geometry=love.graphics.newMesh(vertexFormatLines,vertices,"lines")
Then to draw it like this:
love.graphics.draw(model.geometry)
The error blue screen shows:
Invalid mesh draw mode 'lines', expected one of the 'triangles', 'fan', 'points'.
Any idea how to do a 3D line without the need to simulate some kind of 3D triangle strip?
This is the desired format
local vertexFormatLines={
{"VertexPosition", "float", 3},
{"VertexColor", "byte", 4},
}
local vertices={{0,0,0,1,1,1,1},{0,0,100,1,1,1,1}}
model.geometry=love.graphics.newMesh(vertexFormatLines,vertices,"lines")
Then to draw it like this:
love.graphics.draw(model.geometry)
The error blue screen shows:
Invalid mesh draw mode 'lines', expected one of the 'triangles', 'fan', 'points'.
Any idea how to do a 3D line without the need to simulate some kind of 3D triangle strip?
Re: Groverburger's 3D Engine (g3d) v1.5.2 Release
By generating a cylinder? Here is a function I had some time ago:Rigachupe wrote: ↑Mon Jan 30, 2023 6:43 pm Can you draw a 3D line in this engine? I tried it by defining a vertex array as a 3D line with two points.
This is the desired format
local vertexFormatLines={
{"VertexPosition", "float", 3},
{"VertexColor", "byte", 4},
}
local vertices={{0,0,0,1,1,1,1},{0,0,100,1,1,1,1}}
model.geometry=love.graphics.newMesh(vertexFormatLines,vertices,"lines")
Then to draw it like this:
love.graphics.draw(model.geometry)
The error blue screen shows:
Invalid mesh draw mode 'lines', expected one of the 'triangles', 'fan', 'points'.
Any idea how to do a 3D line without the need to simulate some kind of 3D triangle strip?
Code: Select all
function generate_cylinder(height, radius, nb_segments)
local vertices = {}
local angle_step = 2 * math.pi / nb_segments
local angle = 0
local base_z = -height / 2
local tip_z = height / 2
for i = 1, nb_segments do
local x1 = radius * math.cos(angle)
local y1 = radius * math.sin(angle)
local x2 = radius * math.cos(angle + angle_step)
local y2 = radius * math.sin(angle + angle_step)
-- Base triangle
table.insert(vertices, {0,0,base_z})
table.insert(vertices, {x1,y1,base_z})
table.insert(vertices, {x2,y2,base_z})
-- Tip triangle
table.insert(vertices, {0,0,tip_z})
table.insert(vertices, {x1,y1,tip_z})
table.insert(vertices, {x2,y2,tip_z})
-- Side triangles
table.insert(vertices, {x1,y1,base_z})
table.insert(vertices, {x1,y1,tip_z})
table.insert(vertices, {x2,y2,base_z})
table.insert(vertices, {x2,y2,tip_z})
table.insert(vertices, {x2,y2,base_z})
table.insert(vertices, {x1,y1,tip_z})
angle = angle + angle_step
end
return vertices
end
Edit: I just added UVs and normals to the function above so I'm sharing it if it can help:
Code: Select all
function generate_cylinder(height, radius, nb_segments)
local vertices = {}
local angle_step = 2 * math.pi / nb_segments
local angle = 0
local base_z = -height / 2
local tip_z = height / 2
for i = 1, nb_segments do
local x1 = radius * math.cos(angle)
local y1 = radius * math.sin(angle)
local x2 = radius * math.cos(angle + angle_step)
local y2 = radius * math.sin(angle + angle_step)
-- Base triangle
table.insert(vertices, {0,0,base_z, 0.5,0.5, 0,0,-1})
table.insert(vertices, {x1,y1,base_z, 0,1, 0,0,-1})
table.insert(vertices, {x2,y2,base_z, 1,1, 0,0,-1})
-- Tip triangle
table.insert(vertices, {0,0,tip_z, 0.5,0.5, 0,0,1})
table.insert(vertices, {x1,y1,tip_z, 0,0, 0,0,1})
table.insert(vertices, {x2,y2,tip_z, 1,0, 0,0,1})
-- Side triangles
local edge1_x, edge1_y, edge1_z = x1 - x2, y1 - y2, base_z - tip_z
local edge2_x, edge2_y, edge2_z = x2 - x1, y2 - y1, base_z - tip_z
local normal_x = edge1_y * edge2_z - edge1_z * edge2_y
local normal_y = edge1_z * edge2_x - edge1_x * edge2_z
local normal_z = edge1_x * edge2_y - edge1_y * edge2_x
local normal_length = math.sqrt(normal_x * normal_x + normal_y * normal_y + normal_z * normal_z)
local nx, ny, nz = normal_x / normal_length, normal_y / normal_length, normal_z / normal_length
table.insert(vertices, {x1,y1,base_z, 0, 0.5 - 0.5*y1/radius, nx,ny,nz})
table.insert(vertices, {x1,y1,tip_z, 1, 0.5 - 0.5*y1/radius, nx,ny,nz})
table.insert(vertices, {x2,y2,base_z, 0, 0.5 - 0.5*y2/radius, nx,ny,nz})
table.insert(vertices, {x2,y2,tip_z, 1, 0.5 - 0.5*y2/radius, nx,ny,nz})
table.insert(vertices, {x2,y2,base_z, 0, 0.5 - 0.5*y2/radius, nx,ny,nz})
table.insert(vertices, {x1,y1,tip_z, 1, 0.5 - 0.5*y1/radius, nx,ny,nz})
angle = angle + angle_step
end
return vertices
end
- Attachments
-
- Line3D-2.love
- (14.39 KiB) Downloaded 376 times
-
- Line3D.love
- (13.88 KiB) Downloaded 405 times
Last edited by Bigfoot71 on Thu Feb 02, 2023 3:06 pm, edited 1 time in total.
- Hydrogen Maniac
- Citizen
- Posts: 80
- Joined: Sat Dec 19, 2015 9:59 pm
Re: Groverburger's 3D Engine (g3d) v1.5.2 Release
This looks great ! I really like how you handled the light coming off of lava and the sky.Jasoco wrote: ↑Sun Jan 29, 2023 7:01 am I do wish I could do true lighting though. With shadows and such. Right now it's pretty simplistic. A mixture of calculated point lights and pre-baked lighting. Also every texture can have an associated "bright pixel" atlas for textures that need to have parts that are always full brightness. (For example, the green lights on the doors, the fluorescent lights in the last screenshot and the soda machine facades are all bright pixels.)
Also, everything is pretty much coded tables instead of .obj files. I haven't been able to figure out how to use 3D modeling software and the ones that I like don't export the files with the proper axis "up" that g3d expects. So I find it easier to just construct everything from triangles manually. I feel that uses a lot of memory though. I had a lot of memory problems with some of my earlier experiments where I was trying to make too big of a world with way too many polygons. So I borrowed the method used by Leadhaul for building my maps and creating my sprites.
If you want to give implementing shadows a shot without losing your sanity I recommend looking at the source code of Hoarder's Horrible House Of Stuff. I've had the same issue with modelling software not using the same up vector as g3d but solved it by modifying the objloader to read the y axis as the z axis and vice versa.
I'm way too sober for this...
Re: Groverburger's 3D Engine (g3d) v1.5.2 Release
Much amazing! Care to share your googlings?Jasoco wrote: ↑Sun Jan 29, 2023 7:01 am It's amazing what you can do with shaders when you spend a little time Googling and experimenting.
Screenshot 2023-01-29 at 1.35.47 AM.png
Screenshot 2023-01-29 at 1.33.44 AM.png
Screenshot 2023-01-29 at 1.32.39 AM.png
Screenshot 2023-01-29 at 1.33.22 AM.png
Screenshot 2023-01-29 at 1.36.58 AM.png
Screenshot 2023-01-29 at 1.36.23 AM.png
I do wish I could do true lighting though. With shadows and such. Right now it's pretty simplistic. A mixture of calculated point lights and pre-baked lighting. Also every texture can have an associated "bright pixel" atlas for textures that need to have parts that are always full brightness. (For example, the green lights on the doors, the fluorescent lights in the last screenshot and the soda machine facades are all bright pixels.)
Also, everything is pretty much coded tables instead of .obj files. I haven't been able to figure out how to use 3D modeling software and the ones that I like don't export the files with the proper axis "up" that g3d expects. So I find it easier to just construct everything from triangles manually. I feel that uses a lot of memory though. I had a lot of memory problems with some of my earlier experiments where I was trying to make too big of a world with way too many polygons. So I borrowed the method used by Leadhaul for building my maps and creating my sprites.
EDIT: sorry the double post, thought the forum had post auto-merge feature enabled.
Last edited by vico on Mon Feb 06, 2023 2:24 am, edited 1 time in total.
Re: Groverburger's 3D Engine (g3d) v1.5.2 Release
Okay. I'm trying to resume starting to make a basic voxel demo myself (to learn more about how to use g3d).
I managed to create a cube using lua tables (still dont understand much what each part of the vert table represents) and at same time put a hello world to see how 2d elements would interact with the 3d enviroment (mostly for maybe create an UI on top of that):
But seems like the cube is being "weirdly" rendered (inside-out), like the issue i reported on g3d_voxel, and the 2d test is rendered behind the cube:
I managed to create a cube using lua tables (still dont understand much what each part of the vert table represents) and at same time put a hello world to see how 2d elements would interact with the 3d enviroment (mostly for maybe create an UI on top of that):
Code: Select all
function love.conf(t)
t.window.width = 848
t.window.height = 480
end
Code: Select all
-- Codado por Vico
-- Primeira edição: 12/01/2023
-- À definir a licença
-- Biblioteca g3d
local g3d = require "g3d"
-- Modelo de Cubo
local cube_verts = {
-- top
{0,1,1, 0,0},
{0,0,1, 0,1},
{1,1,1, 1,0},
{0,0,1, 0,1},
{1,0,1, 1,1},
{1,1,1, 1,0},
-- bottom
{0,0,0, 1,0},
{0,1,0, 1,1},
{1,1,0, 0,1},
{1,0,0, 0,0},
{0,0,0, 1,0},
{1,1,0, 0,1},
-- side 1
{0,0,1, 0,0},
{0,0,0, 0,1},
{1,0,1, 1,0},
{0,0,0, 0,1},
{1,0,0, 1,1},
{1,0,1, 1,0},
-- side 2
{0,1,0, 1,1},
{0,1,1, 1,0},
{1,1,1, 0,0},
{1,1,0, 0,1},
{0,1,0, 1,1},
{1,1,1, 0,0},
-- side 3
{0,0,0, 1,1},
{0,0,1, 1,0},
{0,1,1, 0,0},
{0,1,0, 0,1},
{0,0,0, 1,1},
{0,1,1, 0,0},
-- side 4
{1,0,1, 0,0},
{1,0,0, 0,1},
{1,1,1, 1,0},
{1,0,0, 0,1},
{1,1,0, 1,1},
{1,1,1, 1,0},
};
-- Modelo 3D
local dirt = g3d.newModel(cube_verts, "assets/textures/blocks/dirt.png");
local timer = 0;
-- debug
function love.draw()
love.graphics.print("Hello World", 400, 300)
dirt:draw();
end
function love.update(dt)
timer = timer + dt;
g3d.camera.firstPersonMovement(dt);
if love.keyboard.isDown "escape" then
love.event.push "quit"
end
end
function love.mousemoved(x,y, dx,dy)
g3d.camera.firstPersonLook(dx,dy);
end
- Hydrogen Maniac
- Citizen
- Posts: 80
- Joined: Sat Dec 19, 2015 9:59 pm
Re: Groverburger's 3D Engine (g3d) v1.5.2 Release
Rendering the scene to a canvas seems to solve it. I still have no idea why this is the case but the below code should work as intended.
Code: Select all
-- Codado por Vico
-- Primeira edição: 12/01/2023
-- À definir a licença
-- Biblioteca g3d
local g3d = require "g3d"
-- Modelo de Cubo
local cube_verts = {
-- top
{0,1,1, 0,0},
{0,0,1, 0,1},
{1,1,1, 1,0},
{0,0,1, 0,1},
{1,0,1, 1,1},
{1,1,1, 1,0},
-- bottom
{0,0,0, 1,0},
{0,1,0, 1,1},
{1,1,0, 0,1},
{1,0,0, 0,0},
{0,0,0, 1,0},
{1,1,0, 0,1},
-- side 1
{0,0,1, 0,0},
{0,0,0, 0,1},
{1,0,1, 1,0},
{0,0,0, 0,1},
{1,0,0, 1,1},
{1,0,1, 1,0},
-- side 2
{0,1,0, 1,1},
{0,1,1, 1,0},
{1,1,1, 0,0},
{1,1,0, 0,1},
{0,1,0, 1,1},
{1,1,1, 0,0},
-- side 3
{0,0,0, 1,1},
{0,0,1, 1,0},
{0,1,1, 0,0},
{0,1,0, 0,1},
{0,0,0, 1,1},
{0,1,1, 0,0},
-- side 4
{1,0,1, 0,0},
{1,0,0, 0,1},
{1,1,1, 1,0},
{1,0,0, 0,1},
{1,1,0, 1,1},
{1,1,1, 1,0},
};
-- Modelo 3D
local dirt = g3d.newModel(cube_verts, "assets/textures/blocks/dirt.png");
local timer = 0;
-- debug
local canvas = love.graphics.newCanvas(love.graphics.getDimensions())
function love.draw()
love.graphics.setCanvas({canvas,depth=true})
love.graphics.clear()
love.graphics.print("Hello World", 400, 300)
dirt:draw();
love.graphics.setCanvas()
love.graphics.draw(canvas)
end
function love.update(dt)
timer = timer + dt;
g3d.camera.firstPersonMovement(dt);
if love.keyboard.isDown "escape" then
love.event.push "quit"
end
end
function love.mousemoved(x,y, dx,dy)
g3d.camera.firstPersonLook(dx,dy);
end
I threw this together in paint, maybe it will help you understand how the models are built.
I'm way too sober for this...
Re: Groverburger's 3D Engine (g3d) v1.5.2 Release
Thank you so much for this explanation. It really helped me to visualize how it works.Hydrogen Maniac wrote: ↑Mon Feb 06, 2023 8:34 pm I threw this together in paint, maybe it will help you understand how the models are built.
Verts.png
I just have another question: how could i store the model in a text-based format like json? I really dont want to use .obj because i want to allow easy editing of the models (maybe for future modding purposes).
I tried to export a simple cube in JSON model in Blockbench and it spilled the following code:
Code: Select all
{
"credit": "Made with Blockbench",
"elements": [
{
"from": [1, 1, 1],
"to": [2, 2, 2],
"color": 5,
"faces": {
"north": {"uv": [0, 0, 1, 1], "texture": "#missing"},
"east": {"uv": [0, 0, 1, 1], "texture": "#missing"},
"south": {"uv": [0, 0, 1, 1], "texture": "#missing"},
"west": {"uv": [0, 0, 1, 1], "texture": "#missing"},
"up": {"uv": [0, 0, 1, 1], "texture": "#missing"},
"down": {"uv": [0, 0, 1, 1], "texture": "#missing"}
}
}
]
}
Who is online
Users browsing this forum: Bing [Bot] and 3 guests