public void update() { if (freezeRebuild == true) { return; } if (needsRebuild()) { reset(); } double start = TimeSource.currentTime(); bool vboChanged = false; while (shouldKeepTesselating(start) == true) { Tri t = mySplitQueue.Dequeue(); if (t != null) { subdivideTri(t); vboChanged = true; } else { break; } } if (vboChanged) { updateVbo(); } }
bool triInsideViewCone(Tri t) { Vector3 v1, v2, v3; v1 = myVerts[t.i1].Position; v2 = myVerts[t.i2].Position; v3 = myVerts[t.i3].Position; Vector3 sphereCenter = (v1 + v2 + v3) / 3; float sphereRadius = (v1 - sphereCenter).Length; Vector3 U = myCamera.position - (sphereRadius / mySinFov) * myCamera.viewVector; Vector3 D = sphereCenter - U; if (Vector3.Dot(myCamera.viewVector, D) >= D.Length * myCosFov) { // center is inside K’’ D = sphereCenter - myCamera.position; if (-Vector3.Dot(myCamera.viewVector, D) >= D.Length * mySinFov) { // center is inside K’’ and inside K’ return(D.Length <= sphereRadius); } else { // center is inside K’’ and outside K’ return(true); } } else { // center is outside K’’ return(false); } }
void addTriangleToVbo(Tri t) { if (myIndexCount + 3 > MAX_INDEX) { return; } //if (t.backfacing == true) return; if (t.c1 != null) { addTriangleToVbo(t.c1); } if (t.c2 != null) { addTriangleToVbo(t.c2); } if (t.c3 != null) { addTriangleToVbo(t.c3); } if (t.c4 != null) { addTriangleToVbo(t.c4); } //if there are no children add this triangle if (t.c1 == null && t.c2 == null && t.c3 == null && t.c4 == null) { myIndex[myIndexCount++] = t.i1; myIndex[myIndexCount++] = t.i2; myIndex[myIndexCount++] = t.i3; } }
bool culled(Tri t) { if (triInsideViewCone(t) == true) { return(false); } return(true); }
bool elevationErrorTooLarge(Tri t) { float error = t.priority; if (error < myErrorVal) { return(true); } return(false); }
float distancePriority(Tri t) { Vector3 v1, v2, v3; v1 = myVerts[t.i1].Position; v2 = myVerts[t.i2].Position; v3 = myVerts[t.i3].Position; Vector3 triCenter = (v1 + v2 + v3) / 3.0f; float distanceToCamera = (triCenter - myCamera.position).Length; return(1.0f / distanceToCamera); //further things get smaller priority }
double distancePriority(Tri t) { Vector3d v1, v2, v3; v1 = myVerts[t.i1].Position; v2 = myVerts[t.i2].Position; v3 = myVerts[t.i3].Position; Vector3d triCenter = (v1 + v2 + v3) / 3.0f; //get the camera position on the sphere surface Vector3d camPos = ((Vector3d)myCamera.position).Normalized() * myScale; double distanceToCamera = (triCenter - camPos).Length; return(1.0f / distanceToCamera); //further things get smaller priority }
bool triangleTooSmall(Tri t) { Vector3d v1, v2, v3; v1 = myVerts[t.i1].Position; v2 = myVerts[t.i2].Position; v3 = myVerts[t.i3].Position; double dist = (((v1 + v2 + v3) / 3.0f) - (Vector3d)myCamera.position).Length; double e1 = (v2 - v1).Length; double e2 = (v2 - v3).Length; double e3 = (v3 - v1).Length; return((((e1 + e2 + e3) / 3.0f) / dist) < myMinEdgesize); //avg edge length }
public Tri getTop() { for (int i = 0; i < myBuckets.Count; i++) { if (myBuckets[i].Count > 0) { LinkedList <Tri> .Enumerator e = myBuckets[i].GetEnumerator(); e.MoveNext(); Tri t = e.Current; myBuckets[i].RemoveFirst(); return(t); } } return(null); }
public void addTri(Tri t) { if (t.priority > 1.0) { t.priority = 1.0f; } if (t.priority < 0.0) { t.priority = 0.0f; } int b = (int)((1.0 - t.priority) * (myBuckets.Count - 1)); myBuckets[b].AddLast(t); myMaxCount[b]++; }
Tri createTriangle(Tri p, Byte childIndex, uint i1, uint i2, uint i3) { Tri t = myTris[myNextTri++]; t.parent = t; t.id = p.id; t.id.depth += 1; //t.id.index = childIndex; t.i1 = i1; t.i2 = i2; t.i3 = i3; t.c1 = t.c2 = t.c3 = t.c4 = null; t.priority = (float)distancePriority(t); backfacing(t); return(t); }
bool shouldSplit(Tri t) { //check if already split if (t.c1 != null || t.c2 != null || t.c3 != null || t.c4 != null) { return(false); } //depth is too small. the triangles are huuuuuuge, split them anyways if (t.id.depth < 3) { return(true); } //check if it's back facing if (backfacing(t) == true) { return(false); } //is it in the view frustum (uses a bounding sphere/cone test) if (culled(t) == true) { return(false); } //if the triangle's size is too small to be seen, don't split it if (triangleTooSmall(t) == true) { return(false); } //can't split any more than this anyways if (t.id.depth >= 27) { return(false); } return(true); }
double elevationError(Tri t) { Vector3d v1, v2, v3, v12, v23, v31; v1 = myVerts[t.i1].Position; v2 = myVerts[t.i2].Position; v3 = myVerts[t.i3].Position; //calculate the mid points v12 = (v1 + v2) / 2.0f; v23 = (v2 + v3) / 2.0f; v31 = (v3 + v1) / 2.0f; //heights at those points double h12, h23, h31; h12 = 1.0f + myTextureManager.heightAt(v12); h23 = 1.0f + myTextureManager.heightAt(v23); h31 = 1.0f + myTextureManager.heightAt(v31); //distance to those points double d12, d23, d31; d12 = (v12 - (Vector3d)myCamera.position).Length; d23 = (v23 - (Vector3d)myCamera.position).Length; d31 = (v31 - (Vector3d)myCamera.position).Length; //error at those points double e12, e23, e31; e12 = (h12 - v12.Length) / d12; e23 = (h23 - v23.Length) / d23; e31 = (h31 - v31.Length) / d31; //should already be in the range of 0..1 return((e12 + e23 + e31) / 3.0f); }
bool triInsideViewCone(Tri t) { Vector3d v1, v2, v3; v1 = myVerts[t.i1].Position; v2 = myVerts[t.i2].Position; v3 = myVerts[t.i3].Position; Vector3d sphereCenter = (v1 + v2 + v3) / 3; double sphereRadius = (v1 - sphereCenter).Length; //get the camera position on the sphere surface Vector3d camPos = ((Vector3d)myCamera.position).Normalized() * myScale; Vector3d U = camPos - (sphereRadius / mySinFov) * (Vector3d)myCamera.viewVector; Vector3d D = sphereCenter - U; if (Vector3d.Dot((Vector3d)myCamera.viewVector, D) >= D.Length * myCosFov) { // center is inside K’’ D = sphereCenter - camPos; if (-Vector3d.Dot((Vector3d)myCamera.viewVector, D) >= D.Length * mySinFov) { // center is inside K’’ and inside K’ return(D.Length <= sphereRadius); } else { // center is inside K’’ and outside K’ return(true); } } else { // center is outside K’’ return(false); } }
bool backfacing(Tri t) { t.backfacing = false; //is rear facing Vector3d v1, v2, v3; v1 = myVerts[t.i1].Position; v2 = myVerts[t.i2].Position; v3 = myVerts[t.i3].Position; Vector3d edge1 = v2 - v1; Vector3d edge2 = v3 - v1; Vector3d faceNormal = Vector3d.Cross(edge1, edge2); double angle = Vector3d.Dot((v1 - (Vector3d)myCamera.position), faceNormal); if (angle >= 0) { t.backfacing = true; } return(t.backfacing); }
void subdivideTri(Tri t) { if (shouldSplit(t) == false) { return; } Vector3d v1, v2, v3; Vector3d t1, t2, t3; uint i12, i23, i31; V3F1 v12 = new V3F1(); V3F1 v23 = new V3F1(); V3F1 v31 = new V3F1(); //get existing verts v1 = myVerts[t.i1].Position; v2 = myVerts[t.i2].Position; v3 = myVerts[t.i3].Position; //work with normalized positions v1.Normalize(); v2.Normalize(); v3.Normalize(); //new verts between the existing verts t1 = (v1 + v2) / 2; t2 = (v2 + v3) / 2; t3 = (v3 + v1) / 2; //push out to unit sphere t1.Normalize(); t2.Normalize(); t3.Normalize(); v12.Position = t1 * myScale; v23.Position = t2 * myScale; v31.Position = t3 * myScale; //set the height v12.Depth = (float)t.id.depth; //TextureManager.heightAt(v12.Position); v23.Depth = (float)t.id.depth; //TextureManager.heightAt(v23.Position); v31.Depth = (float)t.id.depth; //TmyTextureManager.heightAt(v31.Position); //get the new vertex indexes i12 = myVertCount++; i23 = myVertCount++; i31 = myVertCount++; //add new verts to vert buffer at the new indexes myVerts[i12] = v12; myVerts[i23] = v23; myVerts[i31] = v31; //create new triangles t.c1 = createTriangle(t, 0, i12, i23, i31); t.c2 = createTriangle(t, 1, t.i1, i12, i31); t.c3 = createTriangle(t, 2, i12, t.i2, i23); t.c4 = createTriangle(t, 3, i23, t.i3, i31); mySplitQueue.Enqueue(t.c1); mySplitQueue.Enqueue(t.c2); mySplitQueue.Enqueue(t.c3); mySplitQueue.Enqueue(t.c4); }
public void init() { myLastCameraOrientation = myCamera.myOrientation; myLastCameraPosition = myCamera.position; //6 verts for the octahedron (8 sided dice) myVertCount = 0; myVerts[myVertCount].Position = new Vector3d(0.0, 1.0, 0.0) * myScale; //0-top myVerts[myVertCount].Depth = 0; myVertCount++; myVerts[myVertCount].Position = new Vector3d(0.0, 0.0, -1.0) * myScale; //1-front myVerts[myVertCount].Depth = 0; myVertCount++; myVerts[myVertCount].Position = new Vector3d(1.0, 0.0, 0.0) * myScale; //2-right myVerts[myVertCount].Depth = 0; myVertCount++; myVerts[myVertCount].Position = new Vector3d(0.0, 0.0, 1.0) * myScale; //3-back myVerts[myVertCount].Depth = 0; myVertCount++; myVerts[myVertCount].Position = new Vector3d(-1.0, 0.0, 0.0) * myScale; //4-left myVerts[myVertCount].Depth = 0; myVertCount++; myVerts[myVertCount].Position = new Vector3d(0.0, -1.0, 0.0) * myScale; //5-bottom myVerts[myVertCount].Depth = 0; myVertCount++; //8 faces int myIndexCount = 0; myIndex[myIndexCount++] = 0; myIndex[myIndexCount++] = 2; myIndex[myIndexCount++] = 1; myIndex[myIndexCount++] = 0; myIndex[myIndexCount++] = 3; myIndex[myIndexCount++] = 2; myIndex[myIndexCount++] = 0; myIndex[myIndexCount++] = 4; myIndex[myIndexCount++] = 3; myIndex[myIndexCount++] = 0; myIndex[myIndexCount++] = 1; myIndex[myIndexCount++] = 4; myIndex[myIndexCount++] = 5; myIndex[myIndexCount++] = 1; myIndex[myIndexCount++] = 2; myIndex[myIndexCount++] = 5; myIndex[myIndexCount++] = 2; myIndex[myIndexCount++] = 3; myIndex[myIndexCount++] = 5; myIndex[myIndexCount++] = 3; myIndex[myIndexCount++] = 4; myIndex[myIndexCount++] = 5; myIndex[myIndexCount++] = 4; myIndex[myIndexCount++] = 1; //create the triangles ushort vi = 0; for (int i = 0; i < 8; i++) { Tri t = myTris[myNextTri++]; t.id.myId = 0; t.id.root = (Byte)i; t.i1 = myIndex[vi++]; t.i2 = myIndex[vi++]; t.i3 = myIndex[vi++]; t.c1 = t.c2 = t.c3 = t.c4 = null; t.priority = 1.0f; t.backfacing = false; mySplitQueue.Enqueue(t); } }
public void removeTri(Tri t) { int b = (int)((1.0 - t.priority) * (myBuckets.Count - 1)); myBuckets[b].Remove(t); }