Log In  


I made this demo to quickly demonstrate how to use Blade3D, a 3D rendering API I'm working on. It doesn't make full use of the API, but it does give you a starting point if you want to make your own projects using (this version of) Blade3D. Hopefully I can make a slightly more comprehensive introduction to the API with full documentation in the near future, but for anyone willing to look at the underlying code, it should be pretty easy to accomplish whatever you need with just this template.

Cart #b3d_teapot-10 | 2024-11-30 | Embed ▽ | License: CC4-BY-NC-SA
29

Something that isn't included in the template is a .obj to .ptm converter, which is provided here. It expects the .obj to include material references (not the .mtl file itself) and for the mesh to be triangulated.

local path = env().argv[1]
local output_path = string.sub(path,1,string.find(path,".obj$")).."ptm"

local material_lookup = {}

local material = nil

local obj = {
	v = {},
	vt = {},
	vp = {},
	f = {},
}

-- Each element in an obj starts with an identifier.
-- We can use this identifier to determine how to interpret
-- the rest of the line.
local interps = {
	v = function(ln)
		add(obj.v,vec(ln[2],ln[3],ln[4],1))
	end,
	vt = function(ln)
		add(obj.vt,vec(ln[2],ln[3]))
	end,
	vp = function(ln)
		add(obj.vp,vec(ln[2],ln[3],ln[4]))
	end,
	usemtl = function(ln)
		material = ln[2]
	end,
	f = function(ln)
		local f = {}
		if material_lookup[material] then
			f.mat_index = material_lookup[material]
		else
			add(material_lookup,material)
			material_lookup[material] = #material_lookup
			f.mat_index = #material_lookup
		end

		for i = #ln,2,-1 do
			local indices = split(ln[i],"/")
			local v = {}

			v.v = indices[1]
			if indices[2] ~= "" then v.vt = indices[2] end
			v.vn = indices[3]

			add(f,v)
		end

		add(obj.f,f)
	end,
}

for l in all(split(fetch(path),"\n")) do
	local tokens = split(l," ")
	local interpreter = interps[tokens[1] ]
	if interpreter then interpreter(tokens) end
end

local pts = userdata("f64",4,#obj.v)
for i = 1,#obj.v do
	local v = obj.v[i]
	pts:set(0,i-1,v[0],v[1],v[2],v[3])
end

local uvs = userdata("f64",2,#obj.vt)
for i = 1,#obj.vt do
	local vt = obj.vt[i]
	uvs:set(0,i-1,vt[0],1-vt[1]) -- Top to bottom instead of bottom to top.
end

local materials = {}
for i = 1,#material_lookup do
	add(materials,material_lookup[i])
end

local pt_indices = userdata("f64",3,#obj.f)
local uv_indices = userdata("f64",3,#obj.f)
local material_indices = userdata("f64",#obj.f)

for i = 1,#obj.f do
	local face = obj.f[i]
	material_indices[i-1] = face.mat_index
	local v1,v2,v3 = face[1],face[2],face[3]

	-- Subtract 1 from each index to convert to 0-based.
	pt_indices:set(0,i-1,v1.v-1,v2.v-1,v3.v-1)
	uv_indices:set(0,i-1,v1.vt-1,v2.vt-1,v3.vt-1)
end

local output = {
	pts = pts,
	uvs = uvs,
	materials = materials,

	pt_indices = pt_indices,
	uv_indices = uv_indices,
	material_indices = material_indices,
}

local icon = userdata("u8",16,16,"000000000000010101010000000000000000000000010707070701000000000000000000010707070101070100000000000000010707070107070107010000000000010707070707010701070701000000010d0707010107070107070706010000010d0701070101070707070706010000010d0d07070701070707070606010000010d0d0d070107070707060606010000010d0d0d0d0707070706060606010000010d0d0d0d0d0606060606060601000000010d0d0d0d0d0606060606010000000000010d0d0d0d060606060100000000000000010d0d0d06060601000000000000000000010d0d060601000000000000000000000001010101000000000000")

store(output_path,pod(output,0b111),{icon = icon})

29


wow good job


That's awesome. Is shading dynamic?


1

@maleficmax It's prebaked as a texture. At the moment Blade3D does not have any dynamic shading, although it is being worked on.


2

And now it does.


Holy Molly! The only thing that bothers me here is the CPU load :D
It means we really can't do anything better than pico8 3d stuff, right?
Or even less because it seems that increased picotron cpu frequency was all eaten up by the larger resolution.


@maleficmax The increased resolution isn't actually that big of an issue. It's the triangle preparation that costs the most, and there are things in Picotron's future that will speed up that process by a decent margin. In this demo, the lines are actually taking up a decent chunk of the CPU, since they haven't been so aggressively optimized. I plan to have a wireframe type model at some point as well which should speed up line drawing significantly.


This is honestly so awesome. I can't wait for the guide!



[Please log in to post a comment]