我正在尝试在C#中实现Loop Subdivision算法。 http://www.cs.cmu.edu/afs/cs/academic/class/15462-s13/www/lec_slides/project2_slides.pdf
如何跟踪我找到新顶点的所有边缘。这是我加载线框的Json文件的代码。我已经创建了一个新的类细分来细分网格,但它没有工作,因为有错误。任何人都可以请问我如何细分网格。
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using OpenTK;
using OpenTK.Graphics;
using OpenTK.Graphics.OpenGL;
using System.IO;
using Newtonsoft.Json;
namespace MonkeySubdivision
{
public partial class Form1 : Form
{
Mesh[] meshes0;
Mesh[] meshes1;
Mesh[] meshes2;
bool loaded = false;
public Form1()
{
InitializeComponent();
}
private void display()
{
if (!loaded)
return;
GL.Clear(ClearBufferMask.ColorBufferBit | ClearBufferMask.DepthBufferBit);
GL.Viewport(0, 0, Width, Height);
Matrix4 world = Matrix4.LookAt(Vector3.Zero, Vector3.UnitZ, Vector3.UnitY);
GL.MatrixMode(MatrixMode.Modelview);
GL.LoadMatrix(ref world);
GL.LoadIdentity();
GL.Translate(-0.1f, -0.4f, -5.5f);
meshes0 = LoadJson();
meshes1 = Subdivision.subdivsion(meshes0);
// Subdivide the mesh depending on the numeric value
if (numericUpDown1.Value == 1)
{
// meshes1 = Subdivision.subdivsion(meshes0);
Console.Write("Inside 1st subdivision");
Console.WriteLine("This should be displayed");
meshes0 = meshes1;
}
if (numericUpDown1.Value == 2)
{
Console.Write("Inside 2nd subdivision");
}
if (numericUpDown1.Value == 3)
{
Console.Write("Inside 3rd subdivision");
}
if (numericUpDown1.Value == 4)
{
Console.Write("Inside 4th subdivision");
}
if (numericUpDown1.Value == 5)
{
Console.Write("Inside 5th subdivision");
}
int vertcount = getnumvertices(meshes0);
label2.Text = vertcount.ToString();
int facecount = getnumfaces(meshes0);
label4.Text = facecount.ToString();
// Code To Display the triangles on screen
foreach (Mesh mesh in meshes0)
{
foreach (var face in mesh.Faces)
{
GL.Begin(PrimitiveType.Triangles);
GL.Color3(Color.Yellow);
GL.Vertex3(mesh.Vertices[face.A]);
GL.Vertex3(mesh.Vertices[face.B]);
GL.Vertex3(mesh.Vertices[face.C]);
GL.End();
}
GL.PolygonMode(MaterialFace.Front, PolygonMode.Line);
GL.PolygonMode(MaterialFace.Back, PolygonMode.Line);
GL.Flush();
glControl1.SwapBuffers();
}
}
//Number of faces in a Mesh
private int getnumfaces(Mesh[] meshsub)
{
int count = 0;
foreach (Mesh mesh in meshsub)
{
foreach (var face in mesh.Faces)
count = count + 1;
}
return count;
}
//Number of vertices in a Mesh
private int getnumvertices(Mesh[] meshsub)
{
int count = 0;
foreach (Mesh mesh in meshsub)
{
foreach (var face in mesh.Vertices)
count = count + 1;
}
return count;
}
private void glControl1_Resize(object sender, EventArgs e)
{
GL.Viewport(ClientRectangle.X, ClientRectangle.Y, ClientRectangle.Width, ClientRectangle.Height);
Matrix4 projection = Matrix4.CreatePerspectiveFieldOfView((float)Math.PI / 4, Width / (float)Height, 1.0f, 64.0f);
GL.MatrixMode(MatrixMode.Projection);
GL.LoadMatrix(ref projection);
SetupViewport();
glControl1.Invalidate();
}
private void glControl1_Paint(object sender, PaintEventArgs e)
{
display();
}
private void glControl1_Load(object sender, EventArgs e)
{
loaded = true;
GL.ClearColor(Color.Black);
GL.ShadeModel(ShadingModel.Smooth);
GL.ClearColor(Color.Black);
GL.ClearDepth(1.0f);
GL.Enable(EnableCap.DepthTest);
GL.DepthFunc(DepthFunction.Lequal);
GL.Hint(HintTarget.PerspectiveCorrectionHint, HintMode.Nicest);
SetupViewport();
Application.Idle += Application_Idle; // press TAB twice after +=
}
void Application_Idle(object sender, EventArgs e)
{
// no guard needed -- we hooked into the event in Load handler
while (glControl1.IsIdle)
{
display();
SetupViewport();
}
}
private void SetupViewport()
{
int w = glControl1.Width;
int h = glControl1.Height;
GL.Viewport(ClientRectangle.X, ClientRectangle.Y, ClientRectangle.Width, ClientRectangle.Height);
Matrix4 projection = Matrix4.CreatePerspectiveFieldOfView((float)Math.PI / 4, w / (float)h, 1.0f, 64.0f);
GL.MatrixMode(MatrixMode.Projection);
GL.LoadMatrix(ref projection);
GL.Viewport(0, 0, w, h); // Use all of the glControl painting area
}
// JSON file parser
private Mesh[] LoadJson()
{
var meshes = new List<Mesh>();
using (StreamReader r = new StreamReader("cube.babylon"))
{
string json = r.ReadToEnd();
dynamic jsonObject = JsonConvert.DeserializeObject(json);
for (var meshIndex = 0; meshIndex < jsonObject.meshes.Count; meshIndex++)
{
var verticesArray = jsonObject.meshes[meshIndex].vertices;
// Faces
var indicesArray = jsonObject.meshes[meshIndex].indices;
var uvCount = jsonObject.meshes[meshIndex].uvCount.Value;
var verticesStep = 1;
// Depending of the number of texture's coordinates per vertex
// we're jumping in the vertices array by 6, 8 & 10 windows frame
switch ((int)uvCount)
{
case 0:
verticesStep = 6;
break;
case 1:
verticesStep = 8;
break;
case 2:
verticesStep = 10;
break;
}
// the number of interesting vertices information for us
var verticesCount = verticesArray.Count / verticesStep;
// number of faces is logically the size of the array divided by 3 (A, B, C)
var facesCount = indicesArray.Count / 3;
var mesh = new Mesh(jsonObject.meshes[meshIndex].name.Value, verticesCount, facesCount);
// Filling the Vertices array of our mesh first
for (var index = 0; index < verticesCount; index++)
{
var x = (float)verticesArray[index * verticesStep].Value;
var y = (float)verticesArray[index * verticesStep + 1].Value;
var z = (float)verticesArray[index * verticesStep + 2].Value;
mesh.Vertices[index] = new Vector3(x, y, z);
}
// Then filling the Faces array
for (var index = 0; index < facesCount; index++)
{
var a = (int)indicesArray[index * 3].Value;
var b = (int)indicesArray[index * 3 + 1].Value;
var c = (int)indicesArray[index * 3 + 2].Value;
mesh.Faces[index] = new Face { A = a, B = b, C = c };
}
// Getting the position you've set in Blender
var position = jsonObject.meshes[meshIndex].position;
mesh.Position = new Vector3((float)position[0].Value, (float)position[1].Value, (float)position[2].Value);
meshes.Add(mesh);
}
return meshes.ToArray();
}
}
private void Form1_Load(object sender, EventArgs e)
{
glControl1.Resize += new EventHandler(glControl1_Resize);
meshes0 = LoadJson();
meshes1 = Subdivision.subdivsion(meshes0);
}
private void numericUpDown1_ValueChanged(object sender, EventArgs e)
{
}
}
}
细分函数将采用网格,然后根据循环细分算法细分网格。
using OpenTK;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Collections;
namespace MonkeySubdivision
{
class Subdivision
{
public static Mesh[] subdivsion(Mesh[] meshsub)
{
var meshes = new List<Mesh>();
//Vertices of a mesh
//Hashtable edges = new Hashtable();
int verticescount = getnumvertices(meshsub);
Console.WriteLine(verticescount);
int facecount = getnumfaces(meshsub);
int edgecount = verticescount + facecount - 2;
int newvercount = verticescount + edgecount;
int newfacecount = facecount * 4;
Vector3[] NewVertices = new Vector3[newvercount];
var meshnew = new Mesh("subdmesh", newvercount, newfacecount);
foreach (Mesh mesh in meshsub)
{
//for (var j = 0; j < verticescount; j++)
//{
// Console.WriteLine(mesh.Vertices[j]);
// NewVertices[j] = mesh.Vertices[j];
//}
foreach (Mesh mesh2 in meshsub)
{
//for (var index = 0; index < facecount; index++)
//{
// foreach (var faces in mesh.Faces)
// {
// meshnew.Faces[index] = mesh.Faces[index];
// }
//}
int i = 0;
foreach (var face in mesh.Faces)
{
var P0 = face.A;
var P1 = face.B;
var P2 = face.C;
Console.WriteLine("Faces");
Console.WriteLine(P0);
Console.WriteLine(P1);
Console.WriteLine(P2);
NewVertices[i] = getfourthvert(P0, P1, P2, meshsub);
NewVertices[i + 1 ] = getfourthvert(P1, P2, P0, meshsub);
NewVertices[i + 2] = getfourthvert(P2, P0, P1,meshsub);
i = i + 3;
for (var index = verticescount; index < newvercount; index++)
{
meshnew.Vertices[index] = NewVertices[index];
}
/* for(var index = facecount; index < newfacecount; index++)
{
var a = face.A;
var b = (int)indicesArray[index * 3 + 1].Value;
var c = (int)indicesArray[index * 3 + 2].Value;
mesh.Faces[index] = new Face { A = a, B = b, C = c };
}*/
meshes.Add(meshnew);
}
int n = 6;
double num = (3.0 + 2.0 * Math.Cos(2.0 * Math.PI / n));
double beta = 1.0 / n * (5.0 / 8.0 - num * num / 64.0);
}
}
return meshes.ToArray();
}
private static int getnumfaces(Mesh[] meshsub)
{
int count = 0;
foreach (Mesh mesh in meshsub)
{
foreach (var face in mesh.Faces)
count = count + 1;
}
return count;
}
private static int getnumvertices(Mesh[] meshsub)
{
int count = 0;
foreach (Mesh mesh in meshsub)
{
foreach (var vert in mesh.Vertices)
count = count + 1;
}
return count;
}
private static Vector3 getfourthvert(int X0, int X1, int X2, Mesh[] meshsub)
{
int X3;
Vector3 V4 = new Vector3(0, 0, 0);
foreach (Mesh mesh in meshsub)
{
foreach (var face2 in mesh.Faces)
{
var V0 = mesh.Vertices[X0];
var V1 = mesh.Vertices[X1];
var V2 = mesh.Vertices[X2];
var V3 = mesh.Vertices[0];
if ((X0 == face2.A) && (X1 == face2.B))
{
var temp = face2.C;
if (temp != X2)
{
X3 = temp;
V3 = mesh.Vertices[X3];
V4 = (3 * V0 + 3 * V1 + V2 + V3) / 8;
}
}
}
}
Console.WriteLine(V4);
return V4;
}
}
}
答案 0 :(得分:0)
你需要一个Mesh类,它可以包含三个到其他网格的链接。您还可以保留所有网格的列表,但应该是静态的。
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Drawing;
namespace WindowsFormsApplication1
{
public class Mesh
{
static List<Mesh> meshes { get; set; }
static List<PolyGon> polygons { get; set; }
}
public class PolyGon
{
List<Edge> edges { get; set; }
}
public class Edge
{
List<PointF> points { get; set; } //two points
List<PolyGon> parents { get; set; } // two parents
}
}