/// <summary> /// 多边形剪裁 /// </summary> /// <param name="face"></param> /// <param name="wMin"></param> /// <param name="wMax"></param> /// <param name="vertexList"></param> public void HodgmanPolygonClip(FaceTypes face, Vector4 wMin, Vector4 wMax, Vertex[] vertexList) { Vertex s = vertexList[vertexList.Length - 1]; for (int i = 0; i < vertexList.Length; i++) { Vertex p = vertexList[i]; if (Inside(p.ClipPosition, face, wMin, wMax)) { if (Inside(s.ClipPosition, face, wMin, wMax)) { this.mOutputList.Add(p); } else { this.mOutputList.Add(Intersect(s, p, face, wMin, wMax)); this.mOutputList.Add(vertexList[i]); } } else if (Inside(s.ClipPosition, face, wMin, wMax)) { this.mOutputList.Add(Intersect(s, p, face, wMin, wMax)); } s = vertexList[i]; } }
public Face(int a, int b, int c) { this.A = a; this.B = b; this.C = c; FaceType = FaceTypes.NONE; }
public BoundedSpace(FaceTypes tag, Bounds b, Vector3 forward) { tags = new BoundedSpaceTags(tag); this.bounds = b; neighbors = new Dictionary <Vector3, BoundedSpace>(); setForwardAndUp(forward, Vector3.forward); }
public Face(int a, int b, int c, FaceTypes face) { this.A = a; this.B = b; this.C = c; this.FaceType = face; }
public HashSet <Cell> getCellsByAttribute(FaceTypes tag) { var output = new HashSet <Cell>(); output.UnionWith(cells.Values.ToList().FindAll(x => x.cellContainsAttribute(tag))); return(output); }
/// <summary> /// 判断是否在多边形内 /// </summary> /// <param name="p"></param> /// <param name="face"></param> /// <param name="wMin"></param> /// <param name="wMax"></param> /// <returns></returns> bool Inside(Vector4 p, FaceTypes face, Vector4 wMin, Vector4 wMax) { bool mark = true; switch (face) { case FaceTypes.LEFT: if (p.X < wMin.X) { mark = false; } break; case FaceTypes.RIGHT: if (p.X > wMax.X) { mark = false; } break; case FaceTypes.BUTTOM: if (p.Y < wMin.Y) { mark = false; } break; case FaceTypes.TOP: if (p.Y > wMax.Y) { mark = false; } break; case FaceTypes.NEAR: if (p.Z < wMin.Z) { mark = false; } break; case FaceTypes.FAR: if (p.Z > wMax.Z) { mark = false; } break; } if (p.W < 0) { mark = false; } return(mark); }
/// <summary> /// 根据模型的面的方向返回贴图 /// </summary> /// <param name="types"></param> /// <returns></returns> public RenderTexture GetTextureByFace(FaceTypes types) { if (m_TextureMaps.Length == 0) { return(null); } if (types == FaceTypes.NONE) { return(m_TextureMaps[0]); } else { int index = (int)types; if (m_TextureMaps.Length == 6 && index >= 0 && index < 6) { return(m_TextureMaps[index]); } else { return(m_TextureMaps[0]); } } }
/// <summary> /// 求交点, 返回的pos是裁剪空间下坐标 /// </summary> /// <param name="v1"></param> /// <param name="v2"></param> /// <param name="face"></param> /// <param name="wMin"></param> /// <param name="wMax"></param> /// <returns></returns> Vertex Intersect(Vertex v1, Vertex v2, FaceTypes face, Vector4 wMin, Vector4 wMax) { Vertex vertex = new Vertex(); float k1 = 0, k2 = 0, k3 = 0, k4 = 0, k5 = 0, k6 = 0; Vector4 p1 = v1.ClipPosition; Vector4 p2 = v2.ClipPosition; if (p1.X != p2.X) { k1 = (wMin.X - p1.X) / (p2.X - p1.X); k2 = (wMax.X - p1.X) / (p2.X - p1.X); } else { k1 = k2 = 1; } if (p1.Y != p2.Y) { k3 = (wMin.Y - p1.Y) / (p2.Y - p1.Y); k4 = (wMax.Y - p1.Y) / (p2.Y - p1.Y); } else { k3 = k4 = 1; } if (p1.Z != p2.Z) { k5 = (wMin.Z - p1.Z) / (p2.Z - p1.Z); k6 = (wMax.Z - p1.Z) / (p2.Z - p1.Z); } else { k5 = k6 = 1; } Vector4 clipPos = new Vector4(); Vector4 pos = new Vector4(); Color col = new Color(0, 0, 0); Vector4 normal = new Vector4(); Vector2 uv = new Vector2(); switch (face) { case FaceTypes.LEFT: clipPos.X = wMin.X; clipPos.Y = p1.Y + (p2.Y - p1.Y) * k1; clipPos.Z = p1.Z + (p2.Z - p1.Z) * k1; clipPos.W = p1.W + (p2.W - p1.W) * k1; col = MathUntily.Lerp(v1.Color, v2.Color, k1); normal = MathUntily.Lerp(v1.Normal, v2.Normal, k1); pos = MathUntily.Lerp(v1.Position, v2.Position, k1); uv = MathUntily.Lerp(v1.UV, v2.UV, k1); break; case FaceTypes.RIGHT: clipPos.X = wMax.X; clipPos.Y = p1.Y + (p2.Y - p1.Y) * k2; clipPos.Z = p1.Z + (p2.Z - p1.Z) * k2; clipPos.W = p1.W + (p2.W - p1.W) * k2; col = MathUntily.Lerp(v1.Color, v2.Color, k2); normal = MathUntily.Lerp(v1.Normal, v2.Normal, k2); pos = MathUntily.Lerp(v1.Position, v2.Position, k2); uv = MathUntily.Lerp(v1.UV, v2.UV, k2); break; case FaceTypes.BUTTOM: clipPos.Y = wMin.Y; clipPos.X = p1.X + (p2.X - p1.X) * k3; clipPos.Z = p1.Z + (p2.Z - p1.Z) * k3; clipPos.W = p1.W + (p2.W - p1.W) * k3; col = MathUntily.Lerp(v1.Color, v2.Color, k3); normal = MathUntily.Lerp(v1.Normal, v2.Normal, k3); pos = MathUntily.Lerp(v1.Position, v2.Position, k3); uv = MathUntily.Lerp(v1.UV, v2.UV, k3); break; case FaceTypes.TOP: clipPos.Y = wMax.Y; clipPos.X = p1.X + (p2.X - p1.X) * k4; clipPos.Z = p1.Z + (p2.Z - p1.Z) * k4; clipPos.W = p1.W + (p2.W - p1.W) * k4; col = MathUntily.Lerp(v1.Color, v2.Color, k4); normal = MathUntily.Lerp(v1.Normal, v2.Normal, k4); pos = MathUntily.Lerp(v1.Position, v2.Position, k4); uv = MathUntily.Lerp(v1.UV, v2.UV, k4); break; case FaceTypes.NEAR: clipPos.Z = wMin.Z; clipPos.X = p1.X + (p2.X - p1.X) * k5; clipPos.Y = p1.Y + (p2.Y - p1.Y) * k5; clipPos.W = p1.W + (p2.W - p1.W) * k5; col = MathUntily.Lerp(v1.Color, v2.Color, k5); normal = MathUntily.Lerp(v1.Normal, v2.Normal, k5); pos = MathUntily.Lerp(v1.Position, v2.Position, k5); uv = MathUntily.Lerp(v1.UV, v2.UV, k5); break; case FaceTypes.FAR: clipPos.Z = wMax.Z; clipPos.X = p1.X + (p2.X - p1.X) * k6; clipPos.Y = p1.Y + (p2.Y - p1.Y) * k6; clipPos.W = p1.W + (p2.W - p1.W) * k6; col = MathUntily.Lerp(v1.Color, v2.Color, k6); normal = MathUntily.Lerp(v1.Normal, v2.Normal, k6); pos = MathUntily.Lerp(v1.Position, v2.Position, k6); uv = MathUntily.Lerp(v1.UV, v2.UV, k6); break; } vertex.Position = pos; vertex.ClipPosition = clipPos; vertex.ScreenPosition = this.mDevice.ViewPort(clipPos); vertex.Normal = normal; vertex.UV = uv; vertex.Color = col; return(vertex); }
public Geoset1300(BinaryReader br) { TotalSize = br.ReadUInt32(); long end = TotalSize + br.BaseStream.Position; //Vertices if (br.HasTag("VRTX")) { NrOfVertices = br.ReadUInt32(); for (int i = 0; i < NrOfVertices; i++) { Vertices.Add(new CVector3(br)); } } //Normals if (br.HasTag("NRMS")) { NrOfNormals = br.ReadUInt32(); for (int i = 0; i < NrOfNormals; i++) { Normals.Add(new CVector3(br)); } } //TexCoords if (br.HasTag("UVAS")) { NrOfTexCoords = br.ReadUInt32(); //Amount of groups for (int i = 0; i < NrOfNormals * NrOfTexCoords; i++) { TexCoords.Add(new CVector2(br)); } } //Face Group Type if (br.HasTag("PTYP")) { NrOfFaceTypeGroups = br.ReadUInt32(); FaceTypes.AddRange(br.ReadBytes((int)NrOfFaceTypeGroups)); } //Face Groups if (br.HasTag("PCNT")) { NrOfFaceGroups = br.ReadUInt32(); for (int i = 0; i < NrOfFaceGroups; i++) { FaceGroups.Add(br.ReadUInt32()); } } //Indexes if (br.HasTag("PVTX")) { NrOfFaceVertices = br.ReadUInt32(); for (int i = 0; i < NrOfFaceVertices / 3; i++) { FaceVertices.Add(new CVertex(br)); } } //Vertex Groups if (br.HasTag("GNDX")) { NrOfVertexGroupIndices = br.ReadUInt32(); VertexGroupIndices.AddRange(br.ReadBytes((int)NrOfVertexGroupIndices)); } //Matrix Groups if (br.HasTag("MTGC")) { NrOfMatrixGroups = br.ReadUInt32(); for (int i = 0; i < NrOfMatrixGroups; i++) { MatrixGroups.Add(br.ReadUInt32()); } } //Matrix Indexes if (br.HasTag("MATS")) { NrOfMatrixIndexes = br.ReadUInt32(); for (int i = 0; i < NrOfMatrixIndexes; i++) { MatrixIndexes.Add(br.ReadUInt32()); } } //Bone Indexes if (br.HasTag("BIDX")) { NrOfBoneIndexes = br.ReadUInt32(); for (int i = 0; i < NrOfBoneIndexes; i++) { BoneIndexes.Add(br.ReadUInt32()); } } //Bone Weights if (br.HasTag("BWGT")) { NrOfBoneWeights = br.ReadUInt32(); for (int i = 0; i < NrOfBoneWeights; i++) { BoneWeights.Add(br.ReadUInt32()); } } MaterialId = br.ReadUInt32(); SelectionGroup = br.ReadUInt32(); Unselectable = br.ReadUInt32() == 1; Bounds = new CExtent(br); //Extents NrOfExtents = br.ReadUInt32(); for (int i = 0; i < NrOfExtents; i++) { Extents.Add(new CExtent(br)); } //Grouped Vertices for (int i = 0; i < NrOfVertices; i++) { if (!GroupedVertices.ContainsKey(VertexGroupIndices[i])) { GroupedVertices.Add(VertexGroupIndices[i], new List <CVector3>()); } GroupedVertices[VertexGroupIndices[i]].Add(Vertices[i]); } }
public Quad(Vector3 v1, Vector3 v2, Vector3 v3, Vector3 v4, FaceTypes tag) : base(new Vector3[] { v1, v2, v3, v4 }.ToList()) { this.tag = new BoundedSpaceTags(tag); }
public BoundedSpaceTags(FaceTypes tag) { tags = new List <FaceTypes>(); tags.Add(tag); }
/// <summary> /// 网格渲染 /// </summary> /// <param name="scene"></param> /// <param name="device"></param> /// <param name="viewMat"></param> /// <param name="proMat"></param> public void Render(Scene scene, Device device, Matrix4x4 viewMat, Matrix4x4 proMat) { //MVP矩阵,因为输入的点在世界坐标系不需要世界矩阵 Matrix4x4 MVP = m_Transform * viewMat * proMat; foreach (var faces in m_Faces) { Vertex verA = m_Vertices[faces.A]; Vertex verB = m_Vertices[faces.B]; Vertex verC = m_Vertices[faces.C]; Vertex verA2 = new Vertex(); Vertex verB2 = new Vertex(); Vertex verC2 = new Vertex(); if (scene.IsUseLight && scene.Lights != null) { verA2.LightColor = GetLightColor(verA.Position, verA.Normal, scene.Lights, scene.Camera.Position); verB2.LightColor = GetLightColor(verA.Position, verB.Normal, scene.Lights, scene.Camera.Position); verC2.LightColor = GetLightColor(verA.Position, verC.Normal, scene.Lights, scene.Camera.Position); } // 转换到齐次坐标 verA.ClipPosition = device.ToHomogeneousDNC(verA.Position, MVP); verB.ClipPosition = device.ToHomogeneousDNC(verB.Position, MVP); verC.ClipPosition = device.ToHomogeneousDNC(verC.Position, MVP); verA2.Color = verA.Color; verB2.Color = verB.Color; verC2.Color = verC.Color; //对应屏幕坐标 左上角 verA.ScreenPosition = device.ViewPort(verA.ClipPosition); verB.ScreenPosition = device.ViewPort(verB.ClipPosition); verC.ScreenPosition = device.ViewPort(verC.ClipPosition); verA2.ClipPosition = verA.ClipPosition; verA2.ScreenPosition = verA.ScreenPosition; verA2.Position = m_Transform * verA.Position; verA2.UV = verA.UV; verB2.ClipPosition = verB.ClipPosition; verB2.ScreenPosition = verB.ScreenPosition; verB2.Position = m_Transform * verB.Position; verB2.UV = verB.UV; verC2.ClipPosition = verC.ClipPosition; verC2.ScreenPosition = verC.ScreenPosition; verC2.Position = m_Transform * verC.Position; verC2.UV = verC.UV; verA2.Normal = verA.Normal; verB2.Normal = verB.Normal; verC2.Normal = verC.Normal; List <Vertex> list = new List <Vertex>(); list.Add(verA2); list.Add(verB2); list.Add(verC2); Triangle triang1 = new Triangle(verA2, verB2, verC2); //进行裁剪 List <Vertex> triangleVertex = new List <Vertex>(); //放在构造函数中初始化引起list 集合累加 for (FaceTypes face = FaceTypes.LEFT; face <= FaceTypes.FAR; face++) { if (list.Count == 0) { break; } m_Hodgmanclip = new Clip(device); m_Hodgmanclip.HodgmanPolygonClip(face, Device.sClipmin, Device.sClipmax, list.ToArray()); list = m_Hodgmanclip.OutputList; } List <Triangle> tringleList = GetDrawTriangleList(list); if (device.RenderMode == RenderMode.WIREFRAME) { for (int i = 0; i < tringleList.Count; i++) { if (!device.IsInBack(tringleList[i])) { device.DrawLine(device.ViewPort(tringleList[i].Vertices[0].ClipPosition), device.ViewPort(tringleList[i].Vertices[1].ClipPosition), scene, tringleList[i].Vertices[0], tringleList[i].Vertices[1]); device.DrawLine(device.ViewPort(tringleList[i].Vertices[1].ClipPosition), device.ViewPort(tringleList[i].Vertices[2].ClipPosition), scene, tringleList[i].Vertices[1], tringleList[i].Vertices[2]); device.DrawLine(device.ViewPort(tringleList[i].Vertices[2].ClipPosition), device.ViewPort(tringleList[i].Vertices[0].ClipPosition), scene, tringleList[i].Vertices[2], tringleList[i].Vertices[0]); } } } else { if (m_Scanline == null) { m_Scanline = new ScanLine(device); } for (int i = 0; i < tringleList.Count; i++) { if (!device.IsInBack(tringleList[i])) { m_Scanline.ProcessScanLine(tringleList[i], scene, triang1, faces.FaceType, this); } } } } }
public bool cellContainsAttribute(FaceTypes tag) { return(findWallWithAttribute(tag).Count > 0); }
public List <Shape> findWallWithAttribute(FaceTypes t) { return(walls.FindAll(x => x.tag.tags.Contains(t))); }
/// <summary> /// 根据给定的两条线扫描X轴 /// </summary> /// <param name="triangle"></param> /// <param name="y"></param> /// <param name="v1"></param> /// <param name="v2"></param> /// <param name="v3"></param> /// <param name="v4"></param> /// <param name="scene"></param> /// <param name="ort"></param> /// <param name="types"></param> public void ScanLineX(Triangle triangle, int y, Vertex v1, Vertex v2, Vertex v3, Vertex v4, Scene scene, Triangle ort, FaceTypes types, Mesh msh) { Vector4 screen11 = v1.ScreenPosition; Vector4 screen12 = v2.ScreenPosition; Vector4 screen21 = v3.ScreenPosition; Vector4 screen22 = v4.ScreenPosition; var r1 = screen11.Y != screen12.Y ? (y - screen11.Y) / (screen12.Y - screen11.Y) : 0.5f; var r2 = screen21.Y != screen22.Y ? (y - screen21.Y) / (screen22.Y - screen21.Y) : 0.5f; r1 = Clamp(r1); r2 = Clamp(r2); int dx1 = (int)MathUntily.Lerp(screen11.X, screen12.X, r1); int dx2 = (int)MathUntily.Lerp(screen21.X, screen22.X, r2); float z1 = MathUntily.Lerp(screen11.Z, screen12.Z, r1); float z2 = MathUntily.Lerp(screen21.Z, screen22.Z, r2); Color3 c1 = MathUntily.Lerp(v1.Color, v2.Color, r1); Color3 c2 = MathUntily.Lerp(v3.Color, v4.Color, r2); Color3 c3 = new Color3(); Color3 lc1 = MathUntily.Lerp(v1.LightColor, v2.LightColor, r1); Color3 lc2 = MathUntily.Lerp(v3.LightColor, v4.LightColor, r2); Vector4 pos1 = MathUntily.Lerp(v1.Position, v2.Position, r1); Vector4 pos2 = MathUntily.Lerp(v3.Position, v4.Position, r2); Vector4 pos3 = new Vector4(); Vector4 nor1 = MathUntily.Lerp(v1.Normal, v2.Normal, r1); Vector4 nor2 = MathUntily.Lerp(v3.Normal, v4.Normal, r2); Vector4 nor3 = new Vector4(); // 计算线性方程的系数 ort.PreCallLerp(); Vector4 tmppos = new Vector4(); for (int x = dx1; x < dx2; x++) { float r3 = Clamp((float)(x - dx1) / (dx2 - dx1)); pos3 = MathUntily.Lerp(pos1, pos2, r3); float z = MathUntily.Lerp(z1, z2, r3); tmppos.X = x; tmppos.Y = y; tmppos.Z = z; tmppos.W = 0; ort.CallLerp(tmppos); nor3 = ort.GetNormal(); Light light = scene.Lights; if (scene.IsUseLight == false || light == null) { c3 = MathUntily.Lerp(c1, c2, r3); } else { c3 = MathUntily.Lerp(c1, c2, r3) * MathUntily.Lerp(lc1, lc2, r3); } m_UserColor = c3; if (m_Device.RenderMode == RenderMode.TEXTURED || m_Device.RenderMode == RenderMode.CUBETEXTURED) { ort.CallLerp(new Vector4(x, y, 0, 0)); Vector2 uv = ort.GetUV(); FaceTypes typ = types; if (m_Device.RenderMode == RenderMode.TEXTURED) { typ = FaceTypes.NONE; } RenderTexture texture = msh.GetTextureByFace(typ); if (texture != null) { if (scene.IsUseLight == false || light == null) { m_UserColor = texture.GetPixelColor(uv.X, uv.Y); } else { m_UserColor = texture.GetPixelColor(uv.X, uv.Y) * MathUntily.Lerp(lc1, lc2, r3); } } } this.m_Device.DrawPoint(tmppos, m_UserColor); } }
/// <summary> /// 扫描三角形 /// </summary> /// <param name="triangle"></param> /// <param name="scene"></param> /// <param name="ort"></param> public void ProcessScanLine(Triangle triangle, Scene scene, Triangle ort, FaceTypes types, Mesh msh) { Vector4 P1 = triangle.Vertices[0].ScreenPosition; Vector4 P2 = triangle.Vertices[1].ScreenPosition; Vector4 P3 = triangle.Vertices[2].ScreenPosition; Vertex V1 = triangle.Vertices[0]; Vertex V2 = triangle.Vertices[1]; Vertex V3 = triangle.Vertices[2]; // 根据y从小到大排序 if (P1.Y > P2.Y) { Vector4.SwapVector4(ref P1, ref P2); Vertex.SwapVertex(ref V1, ref V2); } if (P2.Y > P3.Y) { Vector4.SwapVector4(ref P2, ref P3); Vertex.SwapVertex(ref V2, ref V3); } if (P1.Y > P2.Y) { Vector4.SwapVector4(ref P1, ref P2); Vertex.SwapVertex(ref V1, ref V2); } //计算斜率 float dp1dp2 = 0, dp1dp3 = 0; if (P2.Y - P1.Y > 0) { dp1dp2 = (P2.X - P1.X) / (P2.Y - P1.Y); } if (P3.Y - P1.Y > 0) { dp1dp3 = (P3.X - P1.X) / (P3.Y - P1.Y); } if (dp1dp2 == 0) { if (P1.X > P2.X) { Vector4.SwapVector4(ref P1, ref P2); Vertex.SwapVertex(ref V1, ref V2); } for (var y = (int)P1.Y; y < (int)P3.Y; y++) { ScanLineX(triangle, (int)y, V1, V3, V2, V3, scene, ort, types, msh); } } Vector4 temp1 = P1; Vector4 temp2 = P2; Vector4 temp3 = P3; if (dp1dp2 > dp1dp3) { for (int y = (int)P1.Y; y <= (int)P3.Y; y++) { if (y < P2.Y) { ScanLineX(triangle, y, V1, V3, V1, V2, scene, ort, types, msh); } else { ScanLineX(triangle, y, V1, V3, V2, V3, scene, ort, types, msh); } } } else { for (int y = (int)P1.Y; y <= (int)P3.Y; y++) { if (y < P2.Y) { ScanLineX(triangle, y, V1, V2, V1, V3, scene, ort, types, msh); } else { ScanLineX(triangle, y, V2, V3, V1, V3, scene, ort, types, msh); } } } }
public Edge(Vector3 p1, Vector3 p2, FaceTypes t) : this(p1, p2) { tag = new BoundedSpaceTags(t); }