- Home /
[Help]New, procedurally generated materials are black.
Hi there.
I'm stuck with problem: I have procedurally generated mesh, so I generate vertices, UV, triangles and Materials.
//some parsing things -------------
BODContainer cont = / Model File Parse Result/;
Mesh mesh = new Mesh();
mesh.subMeshCount = cont.materials.Length; //I have some materials
mesh.vertices = cont.vertices;
mesh.uv = cont.UV;
for (int i = 0; i < cont.materials.Length; i++) //setting triangles for every submesh
mesh.SetTriangles(cont.triangles[i], i);
List<Material> mats = new List<Material>();
Material tmp;
foreach (var item in cont.materials)
{
tmp = new Material(DataBase.Materials[item.material])
{
mainTexture = DataBase.Textures(item.textureIndex),
color = item.diffuse
};
mats.Add(tmp);
}
meshRenderer.materials = mats.ToArray();
gameObject.transform.localScale = new Vector3(1 / (float)cont.objectsize, 1 / (float)cont.objectsize, 1 / (float)cont.objectsize);
meshFilter.mesh = mesh;
meshFilter.mesh.RecalculateNormals();
But, after this magic, I get black model.
I'm absolutely sure that UV, vertices and triangles are correctly formed. And I'm sure that the problem is in the materials. It seems to me that Unity has some problems with the dynamic creation of materials.
I used both new Material and Material.Instanciate - I still get a black model.
If I'm trying to use original material, from what I try to create a new one, everything fine, model is colorful and shiny, as must.
DataBase.Materials[item.material] - return the original material what I need tocopy and edit to current model.
(I'm loading many models what using 1 original material but with separate parameters, so all models must have their own materials)
(Picture is describing situation: on top - what it must be, on bottom - what I'm getting)
Do you execute all this at runtime or at edit time? So is this runtime code or editor code? This of course would not really work when used in an editor script as $$anonymous$$aterials have to be stored as assets.
What exactly does "DataBase.$$anonymous$$aterials[i]" return? Does it actually return a "$$anonymous$$aterial"?
Of course, it's in game. And of course, DataBase.$$anonymous$$aterials return $$anonymous$$aterial. (because DataBase.$$anonymous$$aterials is Dictionary)
Answer by Luminisc · Jul 24, 2017 at 06:40 PM
Ohhh damn it.... Ok, I found the issue, glad to some 3weeked googling.
And the problem not in the materials, no! And not in parsing, everything fine, vertices, uv, triangles - everything fine. And not the materials array assign, nooo. Not mesh issue, not normals.
It's a damned gameObject.transform.localScale !!!
The problem is what the gameObject.transform.localScale become so small (1.0e-5), so unity just don't render it at all.
What is the reason? Anyone know?
Sure, such a small scale will make your mesh vanish due to floating point precision. $$anonymous$$eep in $$anonymous$$d that a single floating point value can go very low since it has a floating point. However adding a very small number to a larger number won't work.
So adding numbers like 1.0e-6 + 2.0e-7 == 1.2e-6 since the numbers are of about equal order. However if you add numbers like "200" (2.0e+2) + 1.0e-5 will result in just 200 again since a float value doesn't have enough significant digits to represent a number like 200.00001
$$anonymous$$eep in $$anonymous$$d that a mesh actually goes through several transformations (scaling, rotation, translation, projection). So the difference between two vertices in a mesh with such a small scaling easily becomes too small.
But how can I scale mesh quickly without using localScale? In my solution, scaling of huge mesh can be performed many times in second. (need indeed mesh, not by using shader)
I don't want to use things like "vertex.x = scale; vertex.y = scale;" etc. for every vertex in mesh.
And without openCL or CUDA computing.
I thing there are must be some more simple solving of this problem.
There is no problem using localScale to scale your object, however only in a reasonable range. At a scale of 1.0 Unity's default unit translation is about 1 unit == 1m. So when you scale the object by a scale of 0.00001 that would mean 1 unit in local space would be only "10µm". That would already be too small to recognise with the naked eye.
$$anonymous$$eep in $$anonymous$$d that you can change the import scale factor of imported models to adjust the base scale of the object on import.
I would strongly recommend that you don't use a localScale that's larger than 100 or smaller than 0.01
Your answer
Follow this Question
Related Questions
Multiple Cars not working 1 Answer
Morph along the 4th dimension 1 Answer
Problem with Cube normalization containing multiple meshes 0 Answers