Flix - Procedural training and Movie making

Also just for some more clarity. My geom extenstion (this one a little modified) does the following when assigning new buffers to a mesh.

------------------------------------------------------------------------------------------------------------

function geom:makeMesh( goname, indices, verts, uvs, normals )

	if(#indices <= 0) then 
		print("[Error] Invalid indices count.")
		return 
	end
	
	local res = go.get(goname, "vertices")
	local iverts = #indices

	local meshdata = {}
	-- positions are required (should assert or something)
	tinsert(meshdata, { name = hash("position"), type=buffer.VALUE_TYPE_FLOAT32, count = 3 } )
	if(normals) then tinsert(meshdata, { name = hash("normal"), type=buffer.VALUE_TYPE_FLOAT32, count = 3 } ) end
	if(uvs) then tinsert(meshdata, { name = hash("texcoord0"), type=buffer.VALUE_TYPE_FLOAT32, count = 2 } ) end
	
	local meshbuf = buffer.create(iverts, meshdata)

	geomextension.setbufferbytesfromtable( meshbuf, "position", indices, verts )
	if(normals) then geomextension.setbufferbytesfromtable( meshbuf, "normal", indices, normals ) end
	if(uvs) then geomextension.setbufferbytesfromtable( meshbuf, "texcoord0", indices, uvs ) end 
		
	-- set the buffer with the vertices on the mesh
	resource.set_buffer(res, meshbuf)
end

------------------------------------------------------------------------------------------------------------

So the problem isnt being able to generate mesh buffer data, but trying to replace the mesh component handle so that it has a new handle. This might be doable in C++ but I’m not certain of that.
If there are examples/methods that can do this, I would be very welcome to suggestions.

I think this specific comment shows the main problem:

local resource_name = "/my_cloned_buffer.bufferc" -- make this unique for each resource!
This means there needs to be a physical resource file for each res that needs to be attached/modified for each instance.

Note: The code includes some helper funcs that copy tables into buffer data for consumption by the buffer.

1)You have factory.
Factory create go with mesh.
2) From url to this mesh. You can get vertices.

local res = go.get("#mesh", "vertices")

If you print vertices you will get something like this
“vertices: “/world/game/go/chunk/chunk.buffer”\n”

3)You can change this buffer. Now all meshes that have vertices “vertices: “/world/game/go/chunk/chunk.buffer”\n” is changed.

resource.set_buffer(res, buf)

4)Also you can change vertices field for you mesh instance.

    -- assign cloned buffer to a mesh component
go.set("/go#mesh", "vertices", buf)```

So for example. You have one factory. You create 10 go. For every go you change vertices. 
Now you have 10 unique meshes with different meshes.

No, this is only name. It was physical resource if this buffer is created by bob when build game.

But you can create this resources in runtime. You will only need string name with .bufferc ending.
This will not create a new file. This .bufferc will be in memory

Ok. Im not sure I understand. How do I make new resource buffers at runtime
Those other bufferc files do not exist.

If you look at my code above. This is exactly what you suggest, but you cannot change the mesh because the resource (go.get("#mesh", “vertices”) ) is shared on all instanced go’s.

Hrm. This is only a url handle? So in the code above I should be able to set res = “randomname.bufferc” ?

< Update > Just tried this (in above code)

local res = "testbuffer_"..string.format("%d", ctr)..".bufferc" -- go.get(goname, "vertices")

Error:

Not really sure how this could work.

1 Like

Yes, look at resource.create_buffer()

NEW: (#7214 ) Create buffer in runtime
Added new function resource.create_buffer to create buffer resources dynamically in runtime. The function takes a buffer object created by other buffer resources, from the C api or via the lua buffer.create function.

1 Like

Again, I think you are not really understanding? I can create buffers no problem. Look at the above code please. It does exactly what you suggest.

However, the problem is attaching those buffers to an instanced go. If you use:
local res = go.get("#mesh", "vertices")
this fetches a resource handle that is a compiled bufferc. Which is done at build time.

If (and I think this is what you are saying) you can make a new resource at runtime with a valid resource handle then that is what should be used. However, just making up a name wont work, because the registry wont have that file? Maybe in C++ I can add something that registers a new file resource that then can be used? Again, it is not clear how your example could possibly work.

Note: In the api there isnt really a “create resource” call that generates a new runtime resource for use. The closest thing I can see is in the C++ api where there is an AddFile, but Im not sure that is whats needed.

More Notes: I was thinking probably the easiest thing that would potentially provide a simple solve is a copy method in the C++ api, that allows the copying of a resource in mem. And then this would be fairly simple to apply (maybe?)

1 Like

You don’t need new file.

You create runtime resource. This is in memory.
This resource will be alived while you have references for it.(If I understand right)

In this example buffer is clonned. But you can use new buffer.

When you create a new resource, you set content for it. So you don’t need file.

local res = resource.get_buffer("/my_buffer_path.bufferc")
    -- create a cloned buffer resource from another resource buffer
    local buf = reource.create_buffer("/my_cloned_buffer.bufferc", { buffer = res })

This is video of my voxels game. I use one factory for chunk. And I can have unique meshes for every chunk. I am creating new buffer resources in runtime.

3 Likes

Try it, when you write some code you will see how it worked:)

1 Like

Hrm. I think you are using different methods. This might be the problem. Im using buffer.create, which is different to resource.create_buffer.

Just to be clear, are you generating instanced go’s at runtime each with a separate mesh objects? Or are you created one mesh, with additional/other buffers on that mesh component? Because that is already something Im doing.

You absolute bloody legend!!! Thankyou. It was the commands I was using!!!
Ive changed it to this:

------------------------------------------------------------------------------------------------------------
local ctr = 0
function geom:makeMesh( goname, indices, verts, uvs, normals )

	if(#indices <= 0) then 
		print("[Error] Invalid indices count.")
		return 
	end
	
	--	local mesh = resource.load("/assets/gotemplate/temp.mesh")
	pprint(goname)
	local res = resource.get_buffer(go.get(goname, "vertices"))	
	-- create a cloned buffer resource from another resource buffer
	local newres = resource.create_buffer("/testbuffer_"..string.format("%d", ctr)..".bufferc", { buffer = res })	
	ctr = ctr + 1
	pprint(newres)
	local iverts = #indices

	local meshdata = {}
	-- positions are required (should assert or something)
	tinsert(meshdata, { name = hash("position"), type=buffer.VALUE_TYPE_FLOAT32, count = 3 } )
	if(normals) then tinsert(meshdata, { name = hash("normal"), type=buffer.VALUE_TYPE_FLOAT32, count = 3 } ) end
	if(uvs) then tinsert(meshdata, { name = hash("texcoord0"), type=buffer.VALUE_TYPE_FLOAT32, count = 2 } ) end
	--{ name = hash("color0"), type=buffer.VALUE_TYPE_FLOAT32, count = 4 }
	
	local meshbuf = buffer.create(iverts, meshdata)

	geomextension.setbufferbytesfromtable( meshbuf, "position", indices, verts )
	if(normals) then geomextension.setbufferbytesfromtable( meshbuf, "normal", indices, normals ) end
	if(uvs) then geomextension.setbufferbytesfromtable( meshbuf, "texcoord0", indices, uvs ) end 
		
	-- set the buffer with the vertices on the mesh
	resource.set_buffer(newres, meshbuf)
	go.set(goname, "vertices", newres)
end

------------------------------------------------------------------------------------------------------------

And it is mostly working - need to obviously change the ctr naming. Will do some testing, I will need to pump up the buffer and mesh limits now too. Thankyou for helping, I was really struggling with how you could possibly have done it without a resource!

Thanks again. And I really appreciate the patience and help.
Also, I apologize for not realizing the code I was using was different. Very sorry. Thankyou again.

5 Likes

@d954mas - Again. Cant thank you enough. It looks like this should work.
Im now having material instancing issues, but thats because many of my naming conventions have moved around so they are referencing the wrong objects. A little piccy:


Yes thats an MQ-9 in the bg. :slight_smile:

2 Likes

Welcome, I Iike to read your posts, you make cool things​:+1::+1:

3 Likes

Thanks mate. You make some astonishing projects yourself. You are quite an inspirational developer, so thanks if it hasnt already been said too much :slight_smile:

2 Likes

It’s thanks to @d954mas that we’ve improved the dynamic buffer system quite a bit during the last year :slight_smile:

6 Likes

Thats awesome. And again, you guys are doing a stellar job too. So its appreciated.
@d954mas and @jhonny.goransson - can I do a similar thing with adding materials to a mesh at runtime?
Going to try it to see if its possible.

< update > possibly not. I guess materials need to be compiled (shader wise). hrm.

I think the go instance material is shared among the others. Changing one material changes all of them. Any way around this? Going through the C++ api atm to see if there is something that might help.

Huh. Ok, maybe there is a way. 4 yrs ago there was this:
Change material for sprite in runtime … < fingers crossed > :slight_smile:

Im really not sure right now. Maybe I need to reapply the material to the gameobject? Since Ive changed the uv’s. Not sure. Trying many things, hopefully there is a simple fix for this also.

1 Like

Little video of the odd material behavior.
Essentially Im spawning a go for every mesh, assigning it a new resource buffer, filling it with the appropriate index, position, uvs and normals data and then setting its textures (if there are any).

Hm ok, but they have a shared material? Otherwise it might look like a batch issue

Its a factory generating an instance of a go with a temp mesh.
That temp mesh has an assigned material. I think that material, if I set its textures, will set it for all instances? Unless I can do something similar as the mesh and create a new one and assign it to the go.

< update > It seems sprites/gui elements have access to materials?
go.get("#gui", "materials")
I think this is a valid call on them? On meshes, this is not the case (cant find property materials).

Did some work on sliders for world env settings (clouds, sun and such). This will be hooked up to the ambient and shadows (when I get that in).

3 Likes