@John I did not manage to find a way to satisfactorial add transparency to a 3D .obj/.mtl model?
If the .material property is defined, one can use material.opacity to add transparency (with material.blendMode=NORMAL).
But if .material is defined it seems to overwrite the loaded .mtl information and the object will be a single colour, so one loses the different colours defined by the .mtl file.
A related question…is there a way to undo a .material property definition, i.e. remove a previously declared material from a model and come back to using the original .mtl information?
@Bri_G i tried what you suggested but did not succeed-maybe i did something wrong. I think the vertex colors are not what the .mtl uses-but i am not sure.
@piinthesky - you can colour an object by texturing using an image or by assigning a colour to each vertex. Are your model faces a uniform colour or are they a part of multicoloured texture?
@piinthesky If you load the model from a file you can use getMaterial(index) (sorry didn’t realise it was undocumented) to get each individual part of the model that uses a separate material. You can then set any of the options on that material. If you try getting a material at an invalid index it might crash though
@John that works! I was confused about what the index was, but then realised it corresponds to the number of the materials used, if there are 2 materials then index =1,2. We also need a getNumberOfMaterials.
@John if i have many instances of the same obj/mtl model when i modify the material properties of one instance it affects all instances. This seems to be a different behaviour from the standard craft model-in this case one can modify the material of each instance independently.
Of course, for each instance i could load in a new version of the same model, but that quickly gets expensive in terms of memory and speed for large models.
@piinthesky Ah I see what you mean. This is an oversight I suppose. You can use entity:get(craft.renderer).material = myMaterial to have a custom material per entity while using the same model. You can use Standard or Specular with .blendMode = NORMAL and .opacity = desired_value and set other values taken from the original material with a new one created per entity you want to have a unique look.
The only problem is it only gives you the one material (whatever the first indexed material is). You could export models so that the first material is the one you want to change, unless you need to change multiple ones. I’ll have to look into how we can have multiple custom materials per entity.
@piinthesky Yeah I think you’ve run into an edge case that I did not consider (sorry), I’ll try my hand at making an example project that does what you want (multiple instances of the same model with multiple sub-meshes each having their own unique materials) and update the API to reflect the changes required.
The api would probably look something like this:
-- Create a randomly coloured material
function randMaterial()
local mat = craft.material(asset.builtin.Materials.Standard)
mat.diffuse = color(math.random(0,255), math.random(0,255), math.random(0,255))
end
-- Load a model with 3 submeshes (each can each have a unique material)
mdl = craft.model(asset.SomeTripleMaterialModel)
-- Create 1000 models and assign 3 random materials to each one
for i = 1,1000 do
local mat1 = randMaterial()
local mat2 = randMaterial()
local mat3 = randMaterial()
local e = scene:entity()
e.x = i
e.model = mdl
e.materials = {mat1, mat2, mat3}
end
There would also be something like e:setMaterial(index, mat) but the .materials property would be a shortcut. The entity material would override any materials on the model itself (including beyond the first submesh if you set them).
Does this sound like it would solve your issues?
If you really need this functionality right away you’ll have to split your model up into single material parts, then add each one as a separate child entity, and assign the entity.material property for each thing you want to have a unique colour per instance.
Ok, I’ve added .materials and :setMaterial(m, index) to the renderer component in craft. I did a test using the same model 100 times with various random colours for each sub mesh. Seems to work fine so far:
It’s not the most efficient thing but using the same model each time does help reduce performance impacts (I didn’t notice any fps drops on my iPad Pro 2018 model)
mesh and model are still technically incompatible, In Codea 4.0 we will have a new runtime with a streamlined API, folding all duplicate types together, so there will only be mesh, shader and material which will all work with each other
assetList() is now deprecated as it uses the old asset system, the way to do it now is:
-- Load all models in spaceKit asset library
local spaceKitAssets = asset.builtin.SpaceKit.all
local spaceKitModels = {}
for k, v in pairs(spaceKitAssets) do
if v.type == MODELS then -- make sure to filter out any non-model assets
spaceKitModels[v.name] = craft.model(v)
end
end
This works with builtin assets, documents, dropbox, the current project and any subfolders as well. So you can have a folder Documents/Models/Widgets/... and use asset.documents.Models.Zombies.all if you want. Technically it also works with projects as well but it can be tricky to make subfolders in them right now.
@John i did not succeed to get your multiple materials to work? I followed the prescription you gave earlier in this post. Is the builtin asset Blocky_Characters.Man a triple material model? In your code above should the function randMaterial() have return mat at the end?