/// <summary> /// Reads one 3D scene from a given file (containing text variant of Wavefront OBJ format). /// Can read GZipped files. /// </summary> /// <param name="fileName">File-name (ending by .gz for gzipped file)</param> /// <param name="scene">Scene to be modified</param> /// <returns>Number of faces read</returns> public int ReadBrep(string fileName, SceneBrep scene) { if (fileName == null || fileName.Length == 0) { return(SceneBrep.NULL); } StreamReader reader; if (fileName.EndsWith(".gz")) { reader = new StreamReader(new GZipStream(new FileStream(fileName, FileMode.Open), CompressionMode.Decompress)); } else { reader = new StreamReader(new FileStream(fileName, FileMode.Open)); } int faces = ReadBrep(reader, scene); reader.Close(); return(faces); }
void AddToScene(SceneBrep scene, List <Vector3> v, int total) { for (int i = total; i > total - v.Count + 1; i--) { scene.AddLine(i, i - 1); } }
private void firstCircle(Vector3 v1, Vector3 v2, SceneBrep scene, Matrix4 m) { Vector3 dif = (v2 - v1) * size; Vector3 rdif = (v2 - v1) * (1 - size); last_circle = createCircleAround(v1, v2); float s = radius / curve.current_count; last_circle = Transforms.scale(last_circle, s, s, s); connect_indices = new int[cdetail]; Vector3 center = getCenter(last_circle); for (int i = 0; i < cdetail; i++) { connect_indices[i] = scene.AddVertex(Vector3.TransformPosition(last_circle[i] + v1, m)); scene.SetNormal(connect_indices[i], Vector3.TransformVector(last_circle[i] - center, m).Normalized()); float r = (last_circle[i].X + v1.X + 1.1f) / 2.5f; float g = (last_circle[i].Y + v1.Y + 1.1f) / 2.5f; float b = (last_circle[i].Z + v1.Z + 1.1f) / 2.5f; scene.SetColor(connect_indices[i], new Vector3(r, g, b)); } for (int i = 0; i < cdetail; i++) { last_circle[i] += v1 + rdif; } }
/// <summary> /// Construct a new Brep solid (preferebaly closed = regular one). /// </summary> /// <param name="scene">B-rep scene to be modified</param> /// <param name="m">Transform matrix (object-space to world-space)</param> /// <param name="param">Shape parameters if needed</param> /// <returns>Number of generated faces (0 in case of failure)</returns> public int AddMesh(SceneBrep scene, Matrix4 m, string param) { parseParams(param); scene.Reserve(10000000); curve = Curve.createCurve(level); firstCircle(curve.current_vertices[0], curve.current_vertices[1], scene, m); int count = 0; for (int i = 1; i < curve.current_vertices.Length - 1; i++) { if (isBent(curve.current_vertices[i - 1], curve.current_vertices[i], curve.current_vertices[i + 1])) { count += createBentPipe(scene, m, curve.current_vertices[i - 1], curve.current_vertices[i], curve.current_vertices[i + 1]); } else { Vector3 dif = curve.current_vertices[i] - curve.current_vertices[i - 1]; for (int j = 0; j < cdetail; j++) { last_circle[j] = last_circle[j] + dif; } } } int l = curve.current_vertices.Length; count += lastCircle(curve.current_vertices[l - 2], curve.current_vertices[l - 1], scene, m); return(count); }
private int lastCircle(Vector3 v1, Vector3 v2, SceneBrep scene, Matrix4 m) { _ = createCircleAround(v1, v2); Vector3 center = getCenter(last_circle); Vector3 dif = (v2 - v1) * size; _ = (v2 - v1) * (1 - size); int[] v = new int[cdetail]; for (int i = 0; i < cdetail; i++) { v[i] = scene.AddVertex(Vector3.TransformPosition(last_circle[i] + dif, m)); scene.SetNormal(v[i], Vector3.TransformVector(last_circle[i] - center, m).Normalized()); float r = (last_circle[i].X + 1.1f) / 2.5f; float g = (last_circle[i].Y + 1.1f) / 2.5f; float b = (last_circle[i].Z + 1.1f) / 2.5f; scene.SetColor(v[i], new Vector3(r, g, b)); } for (int i = 0; i < cdetail - 1; i++) { scene.AddTriangle(connect_indices[i], v[i], connect_indices[i + 1]); scene.AddTriangle(connect_indices[i + 1], v[i], v[i + 1]); } scene.AddTriangle(connect_indices[cdetail - 1], v[cdetail - 1], connect_indices[0]); scene.AddTriangle(connect_indices[0], v[cdetail - 1], v[0]); return(cdetail * 2); }
private int drawKoch(SceneBrep scene, Matrix4 m, string param) { Vector3 A, B, C, D; int one, two, three, four; //float a = 1.0f; A.X = 0; A.Y = 0; A.Z = 0; one = scene.AddVertex(Vector3.TransformPosition(A, m)); B.X = 1.0f; B.Y = 1.0f; B.Z = 0; two = scene.AddVertex(Vector3.TransformPosition(B, m)); C.X = 0; C.Y = 1.0f; C.Z = 1.0f; three = scene.AddVertex(Vector3.TransformPosition(C, m)); D.X = 1.0f; D.Y = 0; D.Z = 1.0f; four = scene.AddVertex(Vector3.TransformPosition(D, m)); scene.AddLine(one, two); scene.AddLine(two, three); scene.AddLine(three, one); scene.AddLine(four, one); scene.AddLine(four, two); scene.AddLine(four, three); drawKochRecursive(depthParam, scene, m, param, A, B, C, D); return(segments + (int)Math.Pow(4, depthParam) + 1); }
public SceneBrep Clone() { SceneBrep tmp = new SceneBrep(); tmp.geometry = new List <Vector3>(geometry); if (normals != null) { tmp.normals = new List <Vector3>(normals); } if (colors != null) { tmp.colors = new List <Vector3>(colors); } if (txtCoords != null) { tmp.txtCoords = new List <Vector2>(txtCoords); } if (vertexPtr != null) { tmp.vertexPtr = new List <int>(vertexPtr); } if (oppositePtr != null) { tmp.oppositePtr = new List <int>(oppositePtr); } tmp.BuildCornerTable(); return(tmp); }
/// <summary> /// Construct a new Brep solid (preferebaly closed = regular one). /// </summary> /// <param name="scene">B-rep scene to be modified</param> /// <param name="m">Transform matrix (object-space to world-space)</param> /// <param name="param">Shape parameters if needed</param> /// <returns>Number of generated faces (0 in case of failure)</returns> public int AddMesh(SceneBrep scene, Matrix4 m, string param) { // {{ TODO: put your Mesh-construction code here parseParams(param); if (bezier) { return(drawBezier(scene, m, param)); } if (tetrahedron) { return(drawTetrahedron(scene, m, param)); } else if (koch) { return(drawKoch(scene, m, param)); } else if (rose) { return(drawRose(scene, m, param)); } else if (octahedron) { int ret = 0; double s = 0.0; double ds = 1.0 / depthParam; double period = paramAngle; double dtheta = period / depthParam; for (int i = 1; i <= depthParam; ++i) { double theta = i * dtheta; System.Drawing.Color c = Raster.Draw.ColorRamp(0.5 * (s + 1.0)); ret += drawOctahedron(scene, m, param, i, new Vector3(c.R / 255.0f, c.G / 255.0f, c.B / 255.0f), s, theta); s += ds; } return(ret); } else if (spiral) { return(drawSpiral(scene, m, param)); } else if (dragon) { if (depthParam > 15) { depthParam = 15; } return(dragonCurve(scene, m, param)); } else { return(drawDefault(scene, m, param)); } // }} }
/// <summary> /// Construct a new Brep solid (preferebaly closed = regular one). /// </summary> /// <param name="scene">B-rep scene to be modified</param> /// <param name="m">Transform matrix (object-space to world-space)</param> /// <param name="param">Shape parameters if needed</param> /// <returns>Number of generated faces (0 in case of failure)</returns> public int AddMesh(SceneBrep scene, Matrix4 m, string param) { // !!!{{ TODO: put your Mesh-construction code here return(CreateTetrahedron(scene, m, Vector3.Zero, 1.0f)); // !!!}} }
/// <summary> /// Construct a new Brep solid (preferebaly closed = regular one). /// </summary> /// <param name="scene">B-rep scene to be modified</param> /// <param name="m">Transform matrix (object-space to world-space)</param> /// <param name="variant">Shape variant if needed</param> /// <returns>Number of generated faces (0 in case of failure)</returns> public int AddMesh( SceneBrep scene, Matrix4 m, float variant ) { // !!!{{ TODO: put your Mesh-construction code here return 0; // !!!}} }
/// <summary> /// Construct a new Brep solid (preferebaly closed = regular one). /// </summary> /// <param name="scene">B-rep scene to be modified</param> /// <param name="m">Transform matrix (object-space to world-space)</param> /// <param name="variant">Shape variant if needed</param> /// <returns>Number of generated faces (0 in case of failure)</returns> public int AddMesh(SceneBrep scene, Matrix4 m, float variant) { // !!!{{ TODO: put your Mesh-construction code here return(0); // !!!}} }
/// <summary> /// Reads one 3D scene from a given stream (containing text variant of Wavefront OBJ format). /// </summary> /// <param name="reader">Already open text reader</param> /// <param name="scene">Scene to be modified</param> /// <returns>Number of faces read</returns> public int ReadBrep( StreamReader reader, SceneBrep scene ) { if ( reader == null ) return SceneBrep.NULL; Debug.Assert( scene != null ); scene.Reset(); return ReadBrep( reader, scene, Matrix4.Identity ); }
private int drawOctahedron(SceneBrep scene, Matrix4 m, string param, float sc, Vector3 color, double s, double theta) { int one, two, three, four, five, six; float localScale = (float)sc; Vector4 row1 = new Vector4((float)Math.Cos(theta), (float)-Math.Sin(theta), 0, 0); Vector4 row2 = new Vector4((float)Math.Sin(theta), (float)Math.Cos(theta), 0, 0); Vector4 row3 = new Vector4(0, 0, 1, 0); Vector4 row4 = new Vector4(0, 0, 0, 1); m = new Matrix4(row1, row2, row3, row4); Vector3 A = new Vector3(localScale, 0, 0); one = scene.AddVertex(Vector3.TransformPosition(A, m)); A = new Vector3(0, localScale, 0); two = scene.AddVertex(Vector3.TransformPosition(A, m)); A = new Vector3(-localScale, 0, 0); three = scene.AddVertex(Vector3.TransformPosition(A, m)); A = new Vector3(0, -localScale, 0); four = scene.AddVertex(Vector3.TransformPosition(A, m)); A = new Vector3(0, 0, localScale); five = scene.AddVertex(Vector3.TransformPosition(A, m)); A = new Vector3(0, 0, -localScale); six = scene.AddVertex(Vector3.TransformPosition(A, m)); scene.SetTxtCoord(one, new Vector2((float)s, (float)s)); scene.SetTxtCoord(two, new Vector2((float)s, (float)s)); scene.SetTxtCoord(three, new Vector2((float)s, (float)s)); scene.SetTxtCoord(four, new Vector2((float)s, (float)s)); scene.SetTxtCoord(five, new Vector2((float)s, (float)s)); scene.SetTxtCoord(six, new Vector2((float)s, (float)s)); scene.SetColor(one, color); scene.SetColor(two, color); scene.SetColor(three, color); scene.SetColor(four, color); scene.SetColor(five, color); scene.SetColor(six, color); scene.AddLine(one, two); scene.AddLine(two, three); scene.AddLine(three, four); scene.AddLine(four, one); scene.AddLine(five, one); scene.AddLine(five, two); scene.AddLine(five, three); scene.AddLine(five, four); scene.AddLine(six, one); scene.AddLine(six, two); scene.AddLine(six, three); scene.AddLine(six, four); return(6); }
private int CreateTetrahedron(SceneBrep scene, Matrix4 m, Vector3 center, float size) { int[] v = new int[4]; float z = (float)(size * Math.Sqrt(0.5)); Vector3 A = new Vector3(size, 0.0f, -z); Vector3 B = new Vector3(-size, 0.0f, -z); Vector3 C = new Vector3(0.0f, size, z); Vector3 D = new Vector3(0.0f, -size, z); // vertices: v[0] = scene.AddVertex(Vector3.TransformPosition(A, m)); v[1] = scene.AddVertex(Vector3.TransformPosition(B, m)); v[2] = scene.AddVertex(Vector3.TransformPosition(C, m)); v[3] = scene.AddVertex(Vector3.TransformPosition(D, m)); // normal vectors: scene.SetNormal(v[0], Vector3.TransformVector(A, m).Normalized()); scene.SetNormal(v[1], Vector3.TransformVector(B, m).Normalized()); scene.SetNormal(v[2], Vector3.TransformVector(C, m).Normalized()); scene.SetNormal(v[3], Vector3.TransformVector(D, m).Normalized()); // texture coordinates: scene.SetTxtCoord(v[0], new Vector2(1.0f, 0.0f)); scene.SetTxtCoord(v[1], new Vector2(0.0f, 0.0f)); scene.SetTxtCoord(v[2], new Vector2(1.0f, 1.0f)); scene.SetTxtCoord(v[3], new Vector2(0.0f, 1.0f)); // colors: long seed = (long)Math.Min(long.MaxValue, (m.Row3.LengthSquared * 10000.0f)); seed = RandomStatic.numericRecipes(seed); float r = (seed & 255) / 255.0f; seed = RandomStatic.numericRecipes(seed); float g = (seed & 255) / 255.0f; seed = RandomStatic.numericRecipes(seed); float b = (seed & 255) / 255.0f; scene.SetColor(v[0], new Vector3(r, g, b)); r = Math.Min(r + 0.2f, 1.0f); scene.SetColor(v[1], new Vector3(r, g, b)); g = Math.Min(g + 0.2f, 1.0f); scene.SetColor(v[2], new Vector3(r, g, b)); b = Math.Min(b + 0.2f, 1.0f); scene.SetColor(v[3], new Vector3(r, g, b)); // triangle faces: scene.AddTriangle(v[0], v[1], v[2]); scene.AddTriangle(v[2], v[1], v[3]); scene.AddTriangle(v[1], v[0], v[3]); scene.AddTriangle(v[2], v[3], v[0]); return(4); }
/// <summary> /// Returns true if vertex lies on the edge of triangle mesh /// </summary> /// <param name="vertex"></param> /// <returns></returns> public static bool IsOnEdge(Vector3 vertex, SceneBrep scene) { bool onEdge = false; var handle = scene.GetVertex(vertex); List <int> trianglePtr = new List <int>(); // get triangles for (int i = 0; i < scene.vertexPtr.Count; i++) { if (scene.vertexPtr[i] == handle) { if (i % 3 == 0) { trianglePtr.Add(i / 3); } else if (i % 3 == 1) { trianglePtr.Add((i - 1) / 3); } else if (i % 3 == 2) { trianglePtr.Add((i - 2) / 3); } } } // is triangle on edge? foreach (var ptr in trianglePtr) { // get handle of corners of triangle var c1 = Scene3D.SceneBrep.tCorner(ptr); var c2 = c1 + 1; var c3 = c1 + 2; if (scene.cOpposite(c1) == -1) { onEdge = true; } else if (scene.cOpposite(c2) == -1) { onEdge = true; } else if (scene.cOpposite(c3) == -1) { onEdge = true; } } return(onEdge); }
/// <summary> /// Construct a new Brep solid (preferebaly closed = regular one). /// </summary> /// <param name="scene">B-rep scene to be modified</param> /// <param name="m">Transform matrix (object-space to world-space)</param> /// <param name="param">Shape parameters if needed</param> /// <returns>Number of generated faces (0 in case of failure)</returns> public int AddMesh(SceneBrep scene, Matrix4 m, string param) { // !!!{{ TODO: put your Mesh-construction code here // if there will be large number of new vertices, reserve space for them to save time: scene.Reserve(4); return(CreateTetrahedron(scene, m, Vector3.Zero, 1.0f)); // !!!}} }
private int drawRose(SceneBrep scene, Matrix4 m, string param) { int number_of_points = segments; double period = Math.PI * d; if ((n % 2 == 0) || (d % 2 == 0)) { period *= 2; } double s = 0.0; double ds = 1.0 / number_of_points; double dtheta = period / number_of_points; List <int> points = new List <int>(); double k = (double)n / d; for (int i = 0; i < number_of_points; i++) { double theta = i * dtheta; double r = scale * Math.Cos(k * theta); float x = (float)(r * Math.Cos(theta * ratioX)); float y = (float)(r * Math.Sin(theta * ratioY)); float z = (float)(r * Math.Cos(theta * i * ratioZ)); if (noRatioZ) { z = (float)(r * Math.Cos(theta)); } if (noRatioX) { x = (float)(r * Math.Cos(theta)); } if (noRatioY) { y = (float)(r * Math.Sin(theta)); } Vector3 A = new Vector3(x, y, z); int v = scene.AddVertex(Vector3.TransformPosition(A, m)); points.Add(v); scene.SetTxtCoord(v, new Vector2((float)s, (float)s)); System.Drawing.Color c = Raster.Draw.ColorRamp(0.5 * (s + 1.0)); scene.SetColor(v, new Vector3(c.R / 255.0f, c.G / 255.0f, c.B / 255.0f)); s += ds; } for (int i = 0; i < number_of_points - 1; i++) { scene.AddLine(points[i], points[i + 1]); } scene.AddLine(points[0], points[points.Count - 1]); return(number_of_points); }
/// <summary> /// Reads one 3D scene from a given stream (containing text variant of Wavefront OBJ format). /// </summary> /// <param name="reader">Already open text reader</param> /// <param name="scene">Scene to be modified</param> /// <returns>Number of faces read</returns> public int ReadBrep(StreamReader reader, SceneBrep scene) { if (reader == null) { return(SceneBrep.NULL); } Debug.Assert(scene != null); scene.Reset(); return(ReadBrep(reader, scene, Matrix4.Identity)); }
internal void RenderSceneJustCurve(SceneBrep scene) { for (int i = 0; i < Vertices.Count; i++) { scene.AddVertex(Vertices[i]); if (i > 0) { scene.AddLine(i - 1, i); } } scene.AddLine(0, Vertices.Count - 1); }
/// <summary> /// Construct a new Brep solid (preferebaly closed = regular one). /// </summary> /// <param name="scene">B-rep scene to be modified</param> /// <param name="m">Transform matrix (object-space to world-space)</param> /// <param name="param">Shape parameters if needed</param> /// <returns>Number of generated faces (0 in case of failure)</returns> public int AddMesh(SceneBrep scene, Matrix4 m, string param) { parseParams(param); scene.Reserve(10000000); Curve c = new Curve(xFreq, yFreq, zFreq, thickness, vertexFreq, circEdgeSize); c.GenerateThingsForScene(m); c.RenderSceneSimpleTube(scene); // c.RenderSceneJustCurve(scene); return(c.GeneratedFaces); }
/// <summary> /// Construct a new Brep solid (preferebaly closed = regular one). /// </summary> /// <param name="scene">B-rep scene to be modified</param> /// <param name="m">Transform matrix (object-space to world-space)</param> /// <param name="param">Shape parameters if needed</param> /// <returns>Number of generated faces (0 in case of failure)</returns> public int AddMesh(SceneBrep scene, Matrix4 m, string param) { // {{ TODO: put your Mesh-construction code here parseParams(param); // If there will be large number of new vertices, reserve space for them to save time. scene.Reserve(segments + 1); double t = 0.0; double dt = maxT / segments; double s = 0.0; // for both texture coordinate & color ramp double ds = 1.0 / segments; int vPrev = 0; Vector3 A; for (int i = 0; i <= segments; i++) { // New vertex's coordinates. A.X = (float)(radius * Math.Cos(kx * t + dx)); A.Y = (float)(radius * Math.Cos(ky * t + dy)); A.Z = (float)(radius * Math.Cos(kz * t + dz)); // New vertex. int v = scene.AddVertex(Vector3.TransformPosition(A, m)); // Vertex attributes. scene.SetTxtCoord(v, new Vector2((float)s, (float)s)); System.Drawing.Color c = Raster.Draw.ColorRamp(0.5 * (s + 1.0)); scene.SetColor(v, new Vector3(c.R / 255.0f, c.G / 255.0f, c.B / 255.0f)); // New line? if (i > 0) { scene.AddLine(vPrev, v); } // Next vertex. t += dt; s += ds; vPrev = v; } // Thick line (for rendering). scene.LineWidth = 3.0f; return(segments); // }} }
/// <summary> /// Reads one 3D scene from a given file (containing text variant of Wavefront OBJ format). /// Can read GZipped files. /// </summary> /// <param name="fileName">File-name (ending by .gz for gzipped file)</param> /// <param name="scene">Scene to be modified</param> /// <returns>Number of faces read</returns> public int ReadBrep( String fileName, SceneBrep scene ) { if ( fileName == null || fileName.Length == 0 ) return SceneBrep.NULL; StreamReader reader; if ( fileName.EndsWith( ".gz" ) ) reader = new StreamReader( new GZipStream( new FileStream( fileName, FileMode.Open ), CompressionMode.Decompress ) ); else reader = new StreamReader( new FileStream( fileName, FileMode.Open ) ); int faces = ReadBrep( reader, scene ); reader.Close(); return faces; }
private void drawTetrahedronRecursive(int depth, SceneBrep scene, Matrix4 m, string param, Vector3 a, Vector3 b, Vector3 c, Vector3 d) { if (depth == 0) { return; } Vector3 stand; stand.X = 0; stand.Y = 0; stand.Z = 0; int ab, ac, ad, bc, bd, cd; Vector3 AB = stand, AC = stand, AD = stand; Vector3 BC = stand, BD = stand; Vector3 CD = stand; calculateMiddle(a, b, c, d, ref AB, ref AC, ref AD, ref BC, ref BD, ref CD); ab = scene.AddVertex(Vector3.TransformPosition(AB, m)); ac = scene.AddVertex(Vector3.TransformPosition(AC, m)); ad = scene.AddVertex(Vector3.TransformPosition(AD, m)); bc = scene.AddVertex(Vector3.TransformPosition(BC, m)); bd = scene.AddVertex(Vector3.TransformPosition(BD, m)); cd = scene.AddVertex(Vector3.TransformPosition(CD, m)); scene.AddLine(ab, ac); scene.AddLine(ac, bc); scene.AddLine(bc, ab); scene.AddLine(ab, bd); scene.AddLine(bd, ad); scene.AddLine(ad, ab); scene.AddLine(ac, ad); scene.AddLine(ad, cd); scene.AddLine(cd, ac); scene.AddLine(bc, cd); scene.AddLine(cd, bd); scene.AddLine(bd, bc); drawTetrahedronRecursive(depth - 1, scene, m, param, AB, b, BC, BD); drawTetrahedronRecursive(depth - 1, scene, m, param, a, AB, AC, AD); drawTetrahedronRecursive(depth - 1, scene, m, param, AC, BC, c, CD); drawTetrahedronRecursive(depth - 1, scene, m, param, AD, BD, CD, d); }
/// <summary> /// Writes the whole B-rep scene to a given text stream (uses text variant of Wavefront OBJ format). /// </summary> /// <param name="writer">Already open text writer</param> /// <param name="scene">Scene to write</param> public void WriteBrep(StreamWriter writer, SceneBrep scene) { if (scene == null || scene.Triangles < 1) { return; } int i; for (i = 0; i < scene.Vertices; i++) { Vector3 v = scene.GetVertex(i); writer.WriteLine(string.Format(CultureInfo.InvariantCulture, "{0} {1} {2} {3}", new object[] { VERTEX, v.X, v.Y, v.Z })); } bool hasNormals = scene.Normals > 0; if (hasNormals) { for (i = 0; i < scene.Vertices; i++) { Vector3 n = scene.GetNormal(i); writer.WriteLine(string.Format(CultureInfo.InvariantCulture, "{0} {1} {2} {3}", new object[] { VERTEX_NORMAL, n.X, n.Y, n.Z })); } } for (i = 0; i < scene.Triangles; i++) { int A, B, C; scene.GetTriangleVertices(i, out A, out B, out C); A++; B++; C++; if (hasNormals) { writer.WriteLine("{0} {1}//{1} {2}//{2} {3}//{3}", FACE, A, B, C); } else { writer.WriteLine("{0} {1} {2} {3}", FACE, A, B, C); } } }
internal void RenderSceneSimpleTube(SceneBrep scene) { int total = -1; for (int i = 0; i < MeshVertices.Count; i++) { for (int j = 0; j < MeshVertices[i].Count; j++) { scene.AddVertex(MeshVertices[i][j]); total++; } //AddToScene(scene, MeshVertices[i], total); if (i > 0) { ConnectTwoCircles(scene, MeshVertices, total, i); } } ConnectTwoCircles(scene, MeshVertices, total, 0); }
void ConnectTwoCircles(SceneBrep scene, List <List <Vector3> > MeshV, int total, int index) { List <int> firstCirc = new List <int>(); List <int> secCirc = new List <int>(); int count = MeshV[index].Count; if (index != 0) { for (int i = total; i > total - count; i--) { firstCirc.Add(i); secCirc.Add(i - count); } //for (int i = 0; i < firstCirc.Count; i++) { // scene.AddLine(firstCirc[i], secCirc[i]); // scene.AddLine(firstCirc[i], secCirc[(i + 1 == secCirc .Count ? 0 : i+1)]); //} } else { for (int i = total; i > total - count; i--) { firstCirc.Add(i); secCirc.Add(total - i + count); } //for (int i = 0; i < firstCirc.Count; i++) { // scene.AddLine(firstCirc[i], secCirc[i]); // scene.AddLine(firstCirc[i], secCirc[(i + 1 == secCirc.Count ? 0 : i+1)]); //} } for (int i = 0; i < firstCirc.Count; i++) { scene.AddTriangle(firstCirc[i], secCirc[i], secCirc[(i + 1 == secCirc.Count ? 0 : i + 1)]); this.GeneratedFaces++; scene.AddTriangle( firstCirc[(i + 1 == firstCirc.Count ? 0 : i + 1)], firstCirc[i], secCirc[(i + 1 == secCirc.Count ? 0 : i + 1)]); this.GeneratedFaces++; } }
public EarClipping(List <int> pointers, Scene3D.SceneBrep scene) { // Polygon has at least 3 vertices if (pointers.Count < 3) { return; } this.Scene = scene; // Get coordinates from vertex pointers PolygonVertices = new List <Vector3>(); pointers.ForEach(x => PolygonVertices.Add(Scene.GetVertex(x))); PrepareNormal(PolygonVertices); polygon = new Polygon(); copy = new Polygon(); CreatePolygon(polygon, PolygonVertices); CreatePolygon(copy, PolygonVertices); }
private int drawTetrahedron(SceneBrep scene, Matrix4 m, string param) { segments = 4; scene.Reserve(segments + (int)Math.Pow(4, depthParam) + 1); /*c.Line(0, 0, 0, c.Height); * c.Line(0, c.Height, c.Width, c.Height / 2); * c.Line(c.Width, c.Height / 2, 0, 0); */ Vector3 A, B, C, D; int one, two, three, four; //float a = 1.0f; A.X = 0; A.Y = 0; A.Z = 0; one = scene.AddVertex(Vector3.TransformPosition(A, m)); B.X = 1.0f; B.Y = 1.0f; B.Z = 0; two = scene.AddVertex(Vector3.TransformPosition(B, m)); C.X = 0; C.Y = 1.0f; C.Z = 1.0f; three = scene.AddVertex(Vector3.TransformPosition(C, m)); D.X = 1.0f; D.Y = 0; D.Z = 1.0f; four = scene.AddVertex(Vector3.TransformPosition(D, m)); scene.AddLine(one, two); scene.AddLine(two, three); scene.AddLine(three, one); scene.AddLine(four, one); scene.AddLine(four, two); scene.AddLine(four, three); drawTetrahedronRecursive(depthParam, scene, m, param, A, B, C, D); return(segments + (int)Math.Pow(4, depthParam) + 1); }
private int drawLineBezier(SceneBrep scene, Matrix4 m, string param, Vector3 P0, Vector3 P1, Vector3 P2) { int segm = 200; float hun = 100.0f; List <int> pointsList = new List <int>(); addCube(scene, m, param); //P0 -= delta; P1 -= delta;P2 -= delta; for (int i = 0; i <= 100; i++) { float t = ((float)(i)) / hun; Vector3 P = (1 - t) * ((1 - t) * P0 + t * P1) + t * ((1 - t) * P1 + t * P2); //float x = (1-t)*(1-t)*x1 + 2*(1-t)*t*x2+t*t*x3; //float y = (1-t)*(1-t)*y1 + 2*(1-t)*t*y2+t*t*y3; pointsList.Add(scene.AddVertex(Vector3.TransformPosition(P, m))); } for (int i = 0; i < pointsList.Count - 1; i++) { scene.AddLine(pointsList[i], pointsList[i + 1]); } int p0, p1, p2; p0 = scene.AddVertex(Vector3.TransformPosition(P0, m)); p1 = scene.AddVertex(Vector3.TransformPosition(P1, m)); p2 = scene.AddVertex(Vector3.TransformPosition(P2, m)); scene.AddLine(p0, p1); scene.AddLine(p1, p2); return(segm + 2); }
private int drawSpiral(SceneBrep scene, Matrix4 m, string param) { int number_of_points = segments; double period = Math.PI * scale; double dtheta = period / number_of_points; List <int> points = new List <int>(); double ds = 1.0 / (double)number_of_points; double s = 0.0; for (int i = 0; i < number_of_points; i++) { double theta = i * dtheta; float x = (float)(s * s * Math.Cos(theta * ratioX)); float y = (float)(s * s * Math.Sin(theta * ratioY)); float z = (float)(s * s); Vector3 A = new Vector3(x, y, z); int v = scene.AddVertex(Vector3.TransformPosition(A, m)); scene.SetTxtCoord(v, new Vector2((float)s, (float)s)); System.Drawing.Color c = Raster.Draw.ColorRamp(0.5 * (s + 1.0)); scene.SetColor(v, new Vector3(c.R / 255.0f, c.G / 255.0f, c.B / 255.0f)); points.Add(v); s += ds; } for (int i = 0; i < number_of_points - 1; i++) { scene.AddLine(points[i], points[i + 1]); } //scene.AddLine(points[0], points[points.Count - 1]); return(number_of_points); }
/// <summary> /// Do Loop subdivision of the input control triangle mesh. /// </summary> /// <param name="scene">Input scene (must not be changed).</param> /// <param name="epsilon">Reference error toleration (size of undivided triangle).</param> /// <param name="normals">Generate normals? (optional)</param> /// <param name="colors">Generate colors? (optional)</param> /// <param name="txtcoord">Generate texture coordinates? (optional)</param> /// <param name="time">Current time for animation (optional)</param> /// <param name="param">Optional additional parameters.</param> /// <returns>Number of generated points.</returns> public int Subdivide(SceneBrep scene, float epsilon, bool normals, bool colors, bool txtcoord, float time, string param) { result = scene.Clone(); // !!!{{ TODO: put your Loop subdivision code here // pilot: do one (trivial) division int triangles = result.Triangles; int tr; for (tr = 0; tr < triangles; tr++) { int A, B, C; result.GetTriangleVertices(tr, out A, out B, out C); Vector3 vA = result.GetVertex(A); Vector3 vB = result.GetVertex(B); Vector3 vC = result.GetVertex(C); Vector3 vA2 = (vB + vC) * 0.5f; Vector3 vB2 = (vA + vC) * 0.5f; Vector3 vC2 = (vA + vB) * 0.5f; int A2 = result.AddVertex(vA2); int B2 = result.AddVertex(vB2); int C2 = result.AddVertex(vC2); result.AddTriangle(B2, C2, A2); result.AddTriangle(B2, A2, C); result.AddTriangle(C2, B, A2); result.SetTriangleVertices(tr, A, C2, B2); } //result.BuildCornerTable(); return(result.Vertices); // !!!}} }
/// <summary> /// Construct a new control mesh for subdivision (formally the Brep solid..). /// </summary> /// <param name="scene">B-rep scene to be modified</param> /// <param name="m">Transform matrix (object-space to world-space)</param> /// <param name="time">Current time in seconds</param> /// <param name="param">Shape parameters if needed</param> public void ControlMesh(SceneBrep scene, Matrix4 m, float time, string param) { // !!!{{ TODO: put your Control-mesh-construction code here List <int> upper = new List <int>(); upper.Add(scene.AddVertex(Vector3.TransformPosition(new Vector3(0, 1, 0), m))); upper.Add(scene.AddVertex(Vector3.TransformPosition(new Vector3(1, 1, 0), m))); upper.Add(scene.AddVertex(Vector3.TransformPosition(new Vector3(1, 1, 1), m))); upper.Add(scene.AddVertex(Vector3.TransformPosition(new Vector3(0, 1, 1), m))); List <int> lower = new List <int>(); lower.Add(scene.AddVertex(Vector3.TransformPosition(new Vector3(0, 0, 0), m))); lower.Add(scene.AddVertex(Vector3.TransformPosition(new Vector3(1, 0, 0), m))); lower.Add(scene.AddVertex(Vector3.TransformPosition(new Vector3(1, 0, 1), m))); lower.Add(scene.AddVertex(Vector3.TransformPosition(new Vector3(0, 0, 1), m))); // Lower face scene.AddTriangle(lower[0], lower[1], lower[2]); scene.AddTriangle(lower[2], lower[3], lower[0]); // Upper face scene.AddTriangle(upper[2], upper[1], upper[0]); scene.AddTriangle(upper[0], upper[3], upper[2]); // Side faces for (int i = 0; i < upper.Count; i++) { int j = i < (upper.Count - 1) ? i + 1 : 0; scene.AddTriangle(upper[i], upper[j], lower[i]); scene.AddTriangle(lower[i], upper[j], lower[j]); } // !!!}} }
/// <summary> /// Reads one 3D scene from a given stream (containing text variant of Wavefront OBJ format). /// </summary> /// <param name="reader">Already open text reader</param> /// <param name="scene">Scene to be modified</param> /// <param name="scene">Matrix for instancing</param> /// <returns>Number of faces read</returns> public int ReadBrep( StreamReader reader, SceneBrep scene, Matrix4 m ) { if ( reader == null ) return SceneBrep.NULL; Debug.Assert( scene != null ); int v0 = scene.Vertices; int faces = 0; List<Vector3> normals = new List<Vector3>( 256 ); int[] f = new int[ 3 ]; do { string line = reader.ReadLine(); if ( line == null ) break; int commentPos = line.IndexOf( COMMENT ); if ( commentPos >= 0 ) line = line.Substring( 0, commentPos ); string[] tokens = line.Split( ' ' ); switch ( tokens[ 0 ] ) { case VERTEX: if ( tokens.Length < 4 ) continue; Vector3 coord; if ( !float.TryParse( tokens[ 1 ], NumberStyles.Float, CultureInfo.InvariantCulture, out coord.X ) || !float.TryParse( tokens[ 2 ], NumberStyles.Float, CultureInfo.InvariantCulture, out coord.Y ) || !float.TryParse( tokens[ 3 ], NumberStyles.Float, CultureInfo.InvariantCulture, out coord.Z ) ) continue; if ( MirrorConversion ) coord.Z = -coord.Z; scene.AddVertex( Vector3.Transform( coord, m ) ); break; case VERTEX_NORMAL: if ( tokens.Length < 4 ) continue; Vector3 norm; if ( !float.TryParse( tokens[ 1 ], NumberStyles.Float, CultureInfo.InvariantCulture, out norm.X ) || !float.TryParse( tokens[ 2 ], NumberStyles.Float, CultureInfo.InvariantCulture, out norm.Y ) || !float.TryParse( tokens[ 3 ], NumberStyles.Float, CultureInfo.InvariantCulture, out norm.Z ) ) continue; if ( MirrorConversion ) norm.Z = -norm.Z; normals.Add( Vector3.TransformNormal( norm, m ) ); break; case FACE: if ( tokens.Length < 4 ) continue; int i; for ( i = 0; i < 3; i++ ) { string[] vt = tokens[ i + 1 ].Split( '/' ); int ti, ni; ti = ni = SceneBrep.NULL; // 0 .. vertex coord index if ( !int.TryParse( vt[ 0 ], out f[ i ] ) ) break; f[ i ] = v0 + f[ i ] - 1; if ( vt.Length >= 2 ) { // 1 .. texture coord index (not yet) int.TryParse( vt[ 1 ], out ti ); ti--; if ( vt.Length >= 3 ) { // 2 .. normal vector index int.TryParse( vt[ 2 ], out ni ); ni--; } } if ( ni >= 0 && ni < normals.Count ) scene.SetNormal( f[ i ], normals[ ni ] ); } if ( i >= 3 ) { scene.AddTriangle( f[ 0 ], f[ 1 ], f[ 2 ] ); faces++; } break; } } while ( !reader.EndOfStream ); return faces; }
/// <summary> /// Reads one 3D scene from a given stream (containing text variant of Wavefront OBJ format). /// </summary> /// <param name="reader">Already open text reader</param> /// <param name="scene">Scene to be modified</param> /// <param name="scene">Matrix for instancing</param> /// <returns>Number of faces read</returns> public int ReadBrep( StreamReader reader, SceneBrep scene, Matrix4 m ) { if ( reader == null ) return SceneBrep.NULL; Debug.Assert( scene != null ); int v0 = scene.Vertices; int lastVertex = v0 - 1; int faces = 0; List<Vector3> normals = new List<Vector3>( 256 ); int lastNormal = -1; int[] f = new int[ 3 ]; do { string line = reader.ReadLine(); if ( line == null ) break; int commentPos = line.IndexOf( COMMENT ); if ( commentPos >= 0 ) line = line.Substring( 0, commentPos ); string[] tokens = line.Split( DELIMITERS , StringSplitOptions.RemoveEmptyEntries ); if ( tokens.Length < 1 ) continue; switch ( tokens[ 0 ] ) { case VERTEX: if ( tokens.Length < 4 ) continue; Vector3 coord; if ( !float.TryParse( tokens[ 1 ], NumberStyles.Float, CultureInfo.InvariantCulture, out coord.X ) || !float.TryParse( tokens[ 2 ], NumberStyles.Float, CultureInfo.InvariantCulture, out coord.Y ) || !float.TryParse( tokens[ 3 ], NumberStyles.Float, CultureInfo.InvariantCulture, out coord.Z ) ) continue; if ( MirrorConversion ) coord.Z = -coord.Z; lastVertex = scene.AddVertex( Vector3.Transform( coord, m ) ); break; case VERTEX_NORMAL: if ( tokens.Length < 4 ) continue; Vector3 norm; if ( !float.TryParse( tokens[ 1 ], NumberStyles.Float, CultureInfo.InvariantCulture, out norm.X ) || !float.TryParse( tokens[ 2 ], NumberStyles.Float, CultureInfo.InvariantCulture, out norm.Y ) || !float.TryParse( tokens[ 3 ], NumberStyles.Float, CultureInfo.InvariantCulture, out norm.Z ) ) continue; if ( MirrorConversion ) norm.Z = -norm.Z; normals.Add( Vector3.TransformNormal( norm, m ) ); lastNormal++; break; case FACE: if ( tokens.Length < 4 ) continue; int N = tokens.Length - 1; if ( f.Length < N ) f = new int[ N ]; int i; for ( i = 0; i < N; i++ ) // read indices for one vertex { string[] vt = tokens[ i + 1 ].Split( '/' ); int ti, ni; ti = ni = 0; // 0 => value not present // 0 .. vertex coord index if ( !int.TryParse( vt[ 0 ], out f[ i ] ) || f[ i ] == 0 ) break; if ( f[ i ] > 0 ) f[ i ] = v0 + f[ i ] - 1; else f[ i ] = lastVertex + 1 - f[ i ]; if ( vt.Length > 1 ) { // 1 .. texture coord index (not yet) if ( !int.TryParse( vt[ 1 ], out ti ) ) ti = 0; if ( vt.Length > 2 ) { // 2 .. normal vector index if ( !int.TryParse( vt[ 2 ], out ni ) ) ni = 0; } } // there was a normal.. if ( ni != 0 ) { if ( ni > 0 ) ni--; else ni = lastNormal + 1 - ni; if ( ni >= 0 && ni < normals.Count ) scene.SetNormal( f[ i ], normals[ ni ] ); } } N = i; for ( i = 1; i < N - 1; i++ ) { scene.AddTriangle( f[ 0 ], f[ i ], f[ i + 1 ] ); faces++; } break; } } while ( !reader.EndOfStream ); return faces; }
/// <summary> /// Writes the whole B-rep scene to a given text stream (uses text variant of Wavefront OBJ format). /// </summary> /// <param name="writer">Already open text writer</param> /// <param name="scene">Scene to write</param> public void WriteBrep( StreamWriter writer, SceneBrep scene ) { if ( scene == null || scene.Triangles < 1 ) return; int i; for ( i = 0; i < scene.Vertices; i++ ) { Vector3 v = scene.GetVertex( i ); writer.WriteLine( String.Format( CultureInfo.InvariantCulture, "{0} {1} {2} {3}", new object[] { VERTEX, v.X, v.Y, v.Z } ) ); } bool hasNormals = scene.Normals > 0; if ( hasNormals ) for ( i = 0; i < scene.Vertices; i++ ) { Vector3 n = scene.GetNormal( i ); writer.WriteLine( String.Format( CultureInfo.InvariantCulture, "{0} {1} {2} {3}", new object[] { VERTEX_NORMAL, n.X, n.Y, n.Z } ) ); } for ( i = 0; i < scene.Triangles; i++ ) { int A, B, C; scene.GetTriangleVertices( i, out A, out B, out C ); A++; B++; C++; if ( hasNormals ) writer.WriteLine( "{0} {1}//{1} {2}//{2} {3}//{3}", FACE, A, B, C ); else writer.WriteLine( "{0} {1} {2} {3}", FACE, A, B, C ); } }
private void drawKochRecursive(int depth, SceneBrep scene, Matrix4 m, string param, Vector3 a, Vector3 b, Vector3 c, Vector3 d) { if (depth == 0) { return; } Vector3 stand; stand.X = 0; stand.Y = 0; stand.Z = 0; int ab, ac, ad, bc, bd, cd, headabc, headadb, headacd, headbdc; Vector3 AB = stand, AC = stand, AD = stand; Vector3 BC = stand, BD = stand; Vector3 CD = stand; calculateMiddle(a, b, c, d, ref AB, ref AC, ref AD, ref BC, ref BD, ref CD); float lengthOfSide = (float)Math.Sqrt((AB.X - BC.X) * (AB.X - BC.X) + (AB.Y - BC.Y) * (AB.Y - BC.Y) + (AB.Z - BC.Z) * (AB.Z - BC.Z)); float height = lengthOfSide * (float)Math.Sqrt(6) / 3.0f; Vector3 headABC = calculateHeightVertex(a, b, c, height); Vector3 headADB = calculateHeightVertex(a, d, b, height); Vector3 headACD = calculateHeightVertex(a, c, d, height); Vector3 headBDC = calculateHeightVertex(b, d, c, height); ab = scene.AddVertex(Vector3.TransformPosition(AB, m)); ac = scene.AddVertex(Vector3.TransformPosition(AC, m)); ad = scene.AddVertex(Vector3.TransformPosition(AD, m)); bc = scene.AddVertex(Vector3.TransformPosition(BC, m)); bd = scene.AddVertex(Vector3.TransformPosition(BD, m)); cd = scene.AddVertex(Vector3.TransformPosition(CD, m)); headabc = scene.AddVertex(Vector3.TransformPosition(headABC, m)); headadb = scene.AddVertex(Vector3.TransformPosition(headADB, m)); headacd = scene.AddVertex(Vector3.TransformPosition(headACD, m)); headbdc = scene.AddVertex(Vector3.TransformPosition(headBDC, m)); scene.AddLine(ab, ac); scene.AddLine(ac, bc); scene.AddLine(bc, ab); scene.AddLine(ab, headabc); scene.AddLine(ac, headabc); scene.AddLine(bc, headabc); scene.AddLine(ab, bd); scene.AddLine(bd, ad); scene.AddLine(ad, ab); scene.AddLine(ab, headadb); scene.AddLine(bd, headadb); scene.AddLine(ad, headadb); scene.AddLine(ac, ad); scene.AddLine(ad, cd); scene.AddLine(cd, ac); scene.AddLine(ac, headacd); scene.AddLine(ad, headacd); scene.AddLine(cd, headacd); scene.AddLine(bc, cd); scene.AddLine(cd, bd); scene.AddLine(bd, bc); scene.AddLine(bc, headbdc); scene.AddLine(bd, headbdc); scene.AddLine(cd, headbdc); drawKochRecursive(depth - 1, scene, m, param, AB, AC, BC, headABC); drawKochRecursive(depth - 1, scene, m, param, AB, BD, AD, headADB); drawKochRecursive(depth - 1, scene, m, param, AD, CD, AC, headACD); drawKochRecursive(depth - 1, scene, m, param, BD, BC, CD, headBDC); }
public SceneBrep Clone() { SceneBrep tmp = new SceneBrep(); tmp.geometry = new List<Vector3>( geometry ); if ( normals != null ) tmp.normals = new List<Vector3>( normals ); if ( colors != null ) tmp.colors = new List<Vector3>( colors ); if ( txtCoords != null ) tmp.txtCoords = new List<Vector2>( txtCoords ); if ( vertexPtr != null ) tmp.vertexPtr = new List<int>( vertexPtr ); if ( oppositePtr != null ) tmp.oppositePtr = new List<int>( oppositePtr ); tmp.BuildCornerTable(); return tmp; }
public void Render( Bitmap output, SceneBrep scene ) { if ( output == null || scene == null ) return; // center of the object = point to look at: double cx = 0.0; double cy = 0.0; double cz = 0.0; float minx = float.MaxValue; float miny = float.MaxValue; float minz = float.MaxValue; float maxx = float.MinValue; float maxy = float.MinValue; float maxz = float.MinValue; int n = scene.Vertices; int i; for ( i = 0; i < n; i++ ) { Vector3 vi = scene.GetVertex( i ); cx += vi.X; cy += vi.Y; cz += vi.Z; if ( vi.X < minx ) minx = vi.X; if ( vi.Y < miny ) miny = vi.Y; if ( vi.Z < minz ) minz = vi.Z; if ( vi.X > maxx ) maxx = vi.X; if ( vi.Y > maxy ) maxy = vi.Y; if ( vi.Z > maxz ) maxz = vi.Z; } Vector3 center = new Vector3( (float)(cx / n), (float)(cy / n), (float)(cz / n) ); float diameter = (float)Math.Sqrt( (maxx - minx) * (maxx - minx) + (maxy - miny) * (maxy - miny) + (maxz - minz) * (maxz - minz) ); if ( Distance < diameter ) Distance = diameter; // and the rest of projection matrix goes here: int width = output.Width; int height = output.Height; float aspect = width / (float)height; double az = Azimuth / 180.0 * Math.PI; double el = Elevation / 180.0 * Math.PI; Vector3 eye = new Vector3( (float)(center.X + Distance * Math.Sin( az ) * Math.Cos( el )), (float)(center.Y + Distance * Math.Sin( el )), (float)(center.Z + Distance * Math.Cos( az ) * Math.Cos( el )) ); Matrix4 modelView = Matrix4.LookAt( eye, center, Vector3.UnitY ); Matrix4 proj; if ( Perspective ) { float vv = (float)(2.0 * Math.Atan2( diameter * 0.5, Distance )); proj = Matrix4.CreatePerspectiveFieldOfView( vv, aspect, 1.0f, 50.0f ); } else { float vHalf = diameter * 0.52f; proj = Matrix4.CreateOrthographicOffCenter( -vHalf, vHalf, -vHalf / aspect, vHalf / aspect, 1.0f, 50.0f ); } Matrix4 compound = Matrix4.Mult( modelView, proj ); Matrix4 viewport = Geometry.SetViewport( 0, 0, width, height ); compound = Matrix4.Mult( compound, viewport ); // wireframe rendering: Graphics gr = Graphics.FromImage( output ); Pen pen = new Pen( Color.FromArgb( 255, 255, 80 ), 1.0f ); n = scene.Triangles; for ( i = 0; i < n; i++ ) { Vector4 A, B, C; scene.GetTriangleVertices( i, out A, out B, out C ); A = Vector4.Transform( A, compound ); B = Vector4.Transform( B, compound ); C = Vector4.Transform( C, compound ); Vector2 a = new Vector2( A.X / A.W, A.Y / A.W ); Vector2 b = new Vector2( B.X / B.W, B.Y / B.W ); Vector2 c = new Vector2( C.X / C.W, C.Y / C.W ); gr.DrawLine( pen, a.X, a.Y, b.X, b.Y ); gr.DrawLine( pen, b.X, b.Y, c.X, c.Y ); gr.DrawLine( pen, c.X, c.Y, a.X, a.Y ); } if ( DrawNormals && scene.Normals > 0 ) { pen = new Pen( Color.FromArgb( 255, 80, 80 ), 1.0f ); n = scene.Vertices; for ( i = 0; i < n; i++ ) { Vector4 V = new Vector4( scene.GetVertex( i ), 1.0f ); Vector3 N = scene.GetNormal( i ); N.Normalize(); N *= diameter * 0.03f; Vector4 W = V + new Vector4( N ); V = Vector4.Transform( V, compound ); W = Vector4.Transform( W, compound ); Vector2 v = new Vector2( V.X / V.W, V.Y / V.W ); Vector2 w = new Vector2( W.X / W.W, W.Y / W.W ); gr.DrawLine( pen, v.X, v.Y, w.X, w.Y ); } } }
/// <summary> /// Generic OBJ-loading scene definition routine. /// </summary> /// <param name="dir">Viewing direction of a camera.</param> /// <param name="FoVy">Field of View in degrees.</param> /// <param name="correction">Value less than 1.0 brings camera nearer.</param> /// <param name="name">OBJ file-name.</param> /// <param name="names">Substitute file-name[s].</param> /// <returns>Number of triangles.</returns> protected static long SceneObj( IRayScene sc, Vector3d dir, double FoVy, double correction, string name, string[] names, double[] surfaceColor ) { Debug.Assert( sc != null ); Vector3 center = Vector3.Zero; // center of the mesh dir.Normalize(); // normalized viewing vector of the camera float diameter = 2.0f; // default scene diameter int faces = 0; // CSG scene: CSGInnerNode root = new CSGInnerNode( SetOperation.Union ); // OBJ file to read: if ( names.Length == 0 || names[ 0 ].Length == 0 ) names = new string[] { name }; string[] paths = Scenes.SmartFindFiles( names ); if ( paths[ 0 ] == null || paths[ 0 ].Length == 0 ) { for ( int i = 0; i < names.Length; i++ ) if ( names[ i ].Length > 0 ) names[ i ] += ".gz"; paths = Scenes.SmartFindFiles( names ); } if ( paths[ 0 ] == null || paths[ 0 ].Length == 0 ) root.InsertChild( new Sphere(), Matrix4d.Identity ); else { // B-rep scene construction: WavefrontObj objReader = new WavefrontObj(); objReader.MirrorConversion = false; SceneBrep brep = new SceneBrep(); faces = objReader.ReadBrep( paths[ 0 ], brep ); brep.BuildCornerTable(); diameter = brep.GetDiameter( out center ); TriangleMesh m = new TriangleMesh( brep ); root.InsertChild( m, Matrix4d.Identity ); } root.SetAttribute( PropertyName.REFLECTANCE_MODEL, new PhongModel() ); root.SetAttribute( PropertyName.MATERIAL, new PhongMaterial( surfaceColor, 0.2, 0.5, 0.4, 32 ) ); root.SetAttribute( PropertyName.COLOR, surfaceColor ); sc.Intersectable = root; // Background color: sc.BackgroundColor = new double[] { 0.0, 0.05, 0.07 }; // Camera: double dist = (0.5 * diameter * correction) / Math.Tan( MathHelper.DegreesToRadians( (float)(0.5 * FoVy) ) ); Vector3d cam = (Vector3d)center - dist * dir; sc.Camera = new StaticCamera( cam, dir, FoVy ); // Light sources: sc.Sources = new LinkedList<ILightSource>(); sc.Sources.Add( new AmbientLightSource( 0.8 ) ); Vector3d lightDir = Vector3d.TransformVector( dir, Matrix4d.CreateRotationY( -2.0 ) ); lightDir = Vector3d.TransformVector( lightDir, Matrix4d.CreateRotationZ( -0.8 ) ); sc.Sources.Add( new PointLightSource( (Vector3d)center + diameter * lightDir, 1.0 ) ); return faces; }