- Home /
Unity View frustum giving me issues
Hi :) I have a procedurally generated mesh. The mesh is very large, and its center is at a different location than the literal center. The problem is... When the mesh center is outside of the view, the entire mesh disappears. Having done some research into this, I found out that this is frustum culling... The solution supposedly is to do mesh.RecalculateBounds. My code is actually all ready doing that, and the mesh actually used to work! However I created some code to delete about 6 tris from the very large mesh of around 128 thousand tris. All of a sudden, I am getting frustum culling issues. I even tried UNDOING the code (only the part that SETS the tris, there is some code that GETS the tris after the bounds are recalculated) and I am still having issues. I've also turned on bounds calculation AFTER I delete the tris... No effect. However, according to Unity this is not even necessary as bounds are recalculated on triangle edit ANYHOW! It would seem that Unity is not properly calculating the bounds (I actually have had issues with normal calculation as well, but I got around that using a different calculation system). Is there a way to get Unity to, A: Forsake frustum culling for this object, or B: Correctly calculate the bounds? Stupid question, but, would manually calculating the bounds of my object to surround my object work?
Answer by aldonaletto · Nov 08, 2011 at 01:20 AM
It seems Unity have some problem about calculating mesh bounds - I've heard about this disappeared mesh issue before. Maybe a better approach could be set yourself the mesh bounds: you can save the min and max x, y and z coordinates when calculating the vertices, then set the bounds with collider.bounds.SetMinMax(min, max):
var max = Vector3.one * Mathf.NegativeInfinity; var min = Vector3.one * Mathf.Infinity; var vert: Vector3; for (...){ vert = ...// calculate each vertice as before... // then check min and max points if (vert.x < min.x) min.x = vert.x; if (vert.x > max.x) max.x = vert.x; if (vert.y < min.y) min.y = vert.y; if (vert.y > max.y) max.y = vert.y; if (vert.z < min.z) min.z = vert.z; if (vert.z > max.z) max.z = vert.z; } ...When all vertices were calculated, set the bounds:
collider.bounds.SetMinMax(min, max);
NOTE: I suppose the calculated bounds will remain valid until you rotate the mesh - since the bounds are aligned to the axes, the bounds should be recalculated after each rotation.
EDITED: I found other questions about this same problem, and the @Lemon answer in this question seems a good way to "fool" the frustum culling and ensure that your mesh will always be considered visible. Basically, @Lemon forces the mesh's bounds to be a big cube in front of the camera, and this trick seems to solve his problem. I posted a modified version of his script, where bounds are saved and modified in LateUpdate, and restored after culling and rendering in OnRenderObject :
Bounds svBounds;
void LateUpdate(){ Transform camTransform = Camera.main.transform; float distToCenter = (Camera.main.farClipPlane - Camera.main.nearClipPlane) / 2.0f; Vector3 center = camTransform.position + camTransform.forward distToCenter; float extremeBound = 500.0f; MeshFilter meshFilter = GetComponent<MeshFilter>(); svBounds = meshFilter.sharedMesh.bounds; meshFilter.sharedMesh.bounds = new Bounds (center, new Vector3.one extremeBound); }
void OnRenderObject(){ MeshFilter meshFilter = GetComponent<MeshFilter>(); meshFilter.sharedMesh.bounds = svBounds; }
None of that is working I'm afraid :( Do you need any more information? Are there any other alternatives?
EDIT Upon doing some testing: The generation of the bounding box its self works, as seen by Gizmos.DrawWireCube(tmesh.bounds.center, tmesh.bounds.size); ($$anonymous$$esh's position is (0,0,0) so no need to add it to the position of the wire cube). So this leads me to believe that the bounding box is NOT the issue!
I found a trick in one answer that may solve your problem. Take a look in my answer - I edited it to include a modified version of this trick.
Answer by KingSharaman · Mar 10, 2012 at 12:54 AM
Use RecalculateBounds() after you assign the mesh to a MeshFilter component. So for example in C#:
GetComponent().mesh = aMeshObject; aMeshObject.RecalculateBounds();
This way it will recalculate renderer bounds.
Answer by KingSharaman · Mar 10, 2012 at 12:54 AM
Use RecalculateBounds() after you assign the mesh to a MeshFilter component. So for example in C#:
GetComponent().mesh = aMeshObject; aMeshObject.RecalculateBounds();
This way it will recalculate renderer bounds.
Answer by KingSharaman · Mar 10, 2012 at 12:53 AM
Use RecalculateBounds() after you assign the mesh to a MeshFilter component. So for example in C#:
GetComponent().mesh = aMeshObject; aMeshObject.RecalculateBounds();
This way it will recalculate renderer bounds.
Your answer
Follow this Question
Related Questions
Getting the mesh component of an object 1 Answer
Camera movement and zoom bounds 0 Answers
Problem with mesh intersection 0 Answers
Getting actual AABB of an object 1 Answer
Improvements to a grass system 0 Answers