public Poly CopyPoly() { Poly p = new Poly(); p.TextureID = TextureID; p.NumberOfVertices = NumberOfVertices; p.plane = plane; p.verts = new Vertex[NumberOfVertices]; Array.Copy(verts, p.verts, NumberOfVertices); return(p); }
public Poly CopyList() { Poly p = CopyPoly(); if (!IsLast) { p.AddPoly(Next.CopyList()); } return(p); }
public int GetNumberOfPolys() { Poly p = Polys; int uiCount = 0; while (p != null) { p = p.Next; uiCount++; } return(uiCount); }
public void AddPoly(Poly poly) { if (Polys == null) { Polys = poly; return; } Poly p = Polys; while (!p.IsLast) { p = p.Next; } p.SetNext(poly); }
public void CalculateAABB() { min = Polys.verts[0].p; max = Polys.verts[0].p; Poly p = Polys; for (int i = 0; i < GetNumberOfPolys; i++) { for (int j = 0; j < p.NumberOfVertices; j++) { // Calculate min if (p.verts[j].p.x < min.x) { min.x = p.verts[j].p.x; } if (p.verts[j].p.y < min.y) { min.y = p.verts[j].p.y; } if (p.verts[j].p.z < min.z) { min.z = p.verts[j].p.z; } // Calculate max if (p.verts[j].p.x > max.x) { max.x = p.verts[j].p.x; } if (p.verts[j].p.y > max.y) { max.y = p.verts[j].p.y; } if (p.verts[j].p.z > max.z) { max.z = p.verts[j].p.z; } } p = p.Next; } }
public void SetNext(Poly poly) { if (IsLast) { Next = poly; return; } Poly p = poly; while (!p.IsLast) { p = p.Next; } p.SetNext(Next); Next = poly; }
public void AddPoly(Poly pPoly_) { if (pPoly_ != null) { if (IsLast) { Next = pPoly_; return; } Poly p = Next; while (!p.IsLast) { p = p.Next; } p.Next = pPoly_; } }
public eCP ClassifyPoly(Poly poly) { bool front = false, back = false; float dist; for (int i = 0; i < poly.NumberOfVertices; i++) { dist = Vector3.Dot(plane.n, poly.verts[i].p) + plane.d; if (dist > 0.001f) { if (back) { return(eCP.SPLIT); } front = true; } else if (dist < -0.001f) { if (front) { return(eCP.SPLIT); } back = true; } } if (front) { return(eCP.FRONT); } else if (back) { return(eCP.BACK); } return(eCP.ONPLANE); }
public void ClipToBrush(Brush brush, bool clipOnPlane) { Poly polyList = null; Poly p = Polys; for (int i = 0; i < GetNumberOfPolys; i++) { Poly clippedPoly = brush.Polys.ClipToList(p, clipOnPlane); if (polyList == null) { polyList = clippedPoly; } else { polyList.AddPoly(clippedPoly); } p = p.Next; } Polys = polyList; }
public void Load(Tokenizer tokenizer) { entityList.Clear(); entities = 0; polygons = 0; textures = 0; while (tokenizer.PeekNextToken().Type != Tokenizer.TokenType.EndOfStream) { var token = tokenizer.GetNextToken(); if (token.Type == Tokenizer.TokenType.StartBlock) { Entity e = new Entity(); Brush brushList = null; token = tokenizer.GetNextToken(); while (token.Type != Tokenizer.TokenType.EndBlock) { switch (token.Type) { case Tokenizer.TokenType.Value: // Key/value pair var value = tokenizer.GetNextToken(); if (value.Type == Tokenizer.TokenType.Value) { e.Properties.Add(token.Contents, value.Contents); } else { throw new FormatException(String.Format("Expected a value, received a {0}", value)); } break; case Tokenizer.TokenType.StartBlock: // Brush Brush b = new Brush(); Face faces = null; int uiFaces = 0; while (tokenizer.PeekNextToken().Type != Tokenizer.TokenType.EndBlock) { Face face = new Face(); Vector3 v1 = Vector3Extension.FromToken(tokenizer); Vector3 v2 = Vector3Extension.FromToken(tokenizer); Vector3 v3 = Vector3Extension.FromToken(tokenizer); face.plane = new Plane(v1, v3, v2); // TODO: read texture maybe? string textureName = tokenizer.GetNextValue(); // parsing int xOffset = Convert.ToInt32(tokenizer.GetNextValue()); int yOffset = Convert.ToInt32(tokenizer.GetNextValue()); int rotation = Convert.ToInt32(tokenizer.GetNextValue()); float xScale = Convert.ToSingle(tokenizer.GetNextValue()); float yScale = Convert.ToSingle(tokenizer.GetNextValue()); face.texAxis = new Plane[] { new Plane { d = xOffset }, new Plane { d = yOffset } }; face.texRotation = rotation; face.texScale = new float[] { xScale, yScale }; if (faces == null) { // assign as the fist face faces = face; } else { // add face to the list faces.AddFace(face); } uiFaces++; //var newFace = new Face(v1, v2, v3, textureName, xOffset, yOffset, rotation, xScale, yScale); //b.AddFace(newFace); } Poly polyList = faces.GetPolys(); // Sort vertices and calculate texture coordinates for every polygon Poly pi = polyList; Face f = faces; for (int c = 0; c < uiFaces; c++) { pi.plane = f.plane; pi.TextureID = f.texture.ID; pi.SortVerticesCW(); //pi.CalculateTextureCoordinates( // f.texture.GetWidth, // f.texture.GetHeight, // f.texAxis[0], f.texAxis[1], // f.texScale[0], f.texScale[1]); f = f.Next; pi = pi.Next; } b.AddPoly(polyList); b.CalculateAABB(); if (brushList == null) { brushList = b; } else { Brush temp = brushList; while (!temp.IsLast) { temp = temp.Next; } temp.SetNext(b); } tokenizer.GetNextToken(); // Brush end block break; default: throw new FormatException(String.Format("Expected either a block start or a value, received a {0}", token)); } token = tokenizer.GetNextToken(); } // End of entity // Perform CSG union if (brushList != null) { e.AddPoly(brushList.MergeList()); brushList = null; polygons += e.GetNumberOfPolys(); } entityList.Add(e); } } Console.WriteLine("Map created."); Console.WriteLine(" -" + entities + " entities loaded."); Console.WriteLine(" -" + polygons + " polygons loaded."); }
public Poly MergeList() { Brush clippedList = CopyList(); Brush clip = clippedList; Brush brush = null; Poly polyList = null; bool clipOnPlane = false; for (int i = 0; i < GetNumberOfBrushes; i++) { brush = this; clipOnPlane = false; for (int j = 0; j < GetNumberOfBrushes; j++) { if (i == j) { clipOnPlane = true; } else { if (clip.AABBIntersect(brush)) { clip.ClipToBrush(brush, clipOnPlane); } } brush = brush.Next; } clip = clip.Next; } clip = clippedList; while (clip != null) { if (clip.GetNumberOfPolys != 0) { // Extract brushes left over polygons and add them to the list Poly p = clip.Polys.CopyList(); if (polyList == null) { polyList = p; } else { polyList.AddPoly(p); } clip = clip.Next; } else { // Brush has no polygons and should be deleted if (clip == clippedList) { clip = clippedList.Next; clippedList.SetNext(null); clippedList = clip; } else { Brush temp = clippedList; while (temp != null) { if (temp.Next == clip) break; temp = temp.Next; } temp.Next = clip.Next; clip.SetNext(null); clip = temp.Next; } } } return polyList; }
/// <summary> /// Create the polygons from the faces /// </summary> public Poly GetPolys() { int nFaces = 0; Face face = this; while (face != null) { face = face.Next; nFaces++; } Poly polyList = null; Face lfi = null; Face lfj = null; Face lfk = null; // Create polygons face = this; for (int c = 0; c < nFaces; c++) { if (polyList == null) { polyList = new Poly(); } else { polyList.AddPoly(new Poly()); } if (c == nFaces - 3) { lfi = face.Next; } else if (c == nFaces - 2) { lfj = face.Next; } else if (c == nFaces - 1) { lfk = face.Next; } face = face.Next; } // Loop through faces and create polygons Poly pi = polyList; for (Face fi = this; fi != lfi; fi = fi.Next) { Poly pj = pi.Next; for (Face fj = fi.Next; fj != lfj; fj = fj.Next) { Poly pk = pj.Next; for (Face fk = fj.Next; fk != lfk; fk = fk.Next) { Vector3 p = Vector3.zero; if (fi.plane.GetIntersection(fj.plane, fk.plane, ref p)) { Face f = this; while (true) { if (f.plane.ClassifyPoints(p) == Plane.eCP.FRONT) { break; } if (!f.IsLast) { Vertex v = new Vertex { p = p }; pi.AddVertex(v); pj.AddVertex(v); pk.AddVertex(v); break; } f = f.Next; } } pk = pk.Next; } pj = pj.Next; } pi = pi.Next; } return(polyList); }
public Poly ClipToList(Poly poly, bool clipOnPlane) { switch (ClassifyPoly(poly)) { case eCP.FRONT: return(poly.CopyPoly()); case eCP.BACK: if (IsLast) { return(null); } return(Next.ClipToList(poly, clipOnPlane)); case eCP.ONPLANE: float angle = Vector3.Dot(plane.n, poly.plane.n) - 1; if (angle < Mathf.EPSILON && angle > -Mathf.EPSILON) { if (!clipOnPlane) { return(poly.CopyPoly()); } } if (IsLast) { return(null); } return(Next.ClipToList(poly, clipOnPlane)); case eCP.SPLIT: Poly front = null; Poly back = null; SplitPoly(poly, ref front, ref back); if (IsLast) { return(front); } Poly backFrags = Next.ClipToList(back, clipOnPlane); if (backFrags == null) { return(front); } if (backFrags == back) { return(poly.CopyPoly()); } front.AddPoly(backFrags); return(front); } return(null); }
public void SplitPoly(Poly poly, ref Poly front, ref Poly back) { Plane.eCP[] cp = new Plane.eCP[poly.NumberOfVertices]; // classify all points for (int i = 0; i < poly.NumberOfVertices; i++) { cp[i] = plane.ClassifyPoints(poly.verts[i].p); } // builds fragments Poly newFront = new Poly(); Poly newBack = new Poly(); newFront.TextureID = poly.TextureID; newBack.TextureID = poly.TextureID; newFront.plane = poly.plane; newBack.plane = poly.plane; for (int i = 0; i < poly.NumberOfVertices; i++) { // Add point to appropriate list switch (cp[i]) { case Plane.eCP.FRONT: newFront.AddVertex(poly.verts[i]); break; case Plane.eCP.BACK: newBack.AddVertex(poly.verts[i]); break; case Plane.eCP.ONPLANE: newFront.AddVertex(poly.verts[i]); newBack.AddVertex(poly.verts[i]); break; } // Check if edges should be split int iNext = i + 1; bool ignore = false; if (i == (poly.NumberOfVertices - 1)) { iNext = 0; } if (cp[i] == Plane.eCP.ONPLANE && cp[iNext] != Plane.eCP.ONPLANE) { ignore = true; } else if (cp[iNext] == Plane.eCP.ONPLANE && cp[i] != Plane.eCP.ONPLANE) { ignore = true; } if (!ignore && (cp[i] != cp[iNext])) { Vertex v = new Vertex(); // New vertex created by splitting float p = 0f; // Percentage between the two points plane.GetIntersection(poly.verts[i].p, poly.verts[iNext].p, v.p, p); v.tex[0] = poly.verts[iNext].tex[0] - poly.verts[i].tex[0]; v.tex[1] = poly.verts[iNext].tex[1] - poly.verts[i].tex[1]; v.tex[0] = poly.verts[i].tex[0] + (p * v.tex[0]); v.tex[1] = poly.verts[i].tex[1] + (p * v.tex[1]); newFront.AddVertex(v); newBack.AddVertex(v); } } newFront.CalculatePlane(); newBack.CalculatePlane(); front = newFront; back = newBack; }