I am trying to implement Loop Subdivision algorithm in C#.
http://www.cs.cmu.edu/afs/cs/academic/class/15462-s13/www/lec_slides/project2_slides.pdf
How can i keep track of all the edges in which I have found out the new vertex. Here's my code to load Json file of the wireframe. I have created a new class subdivision to subdivide the mesh, but it is not working as there are errors. Can anyone please throw some light on how can I subdivide the mesh.
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)
{
}
}
}
Subdivision function will take the mesh and then subdivide the mesh according to the loop subdivision algorithm.
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;
}
}
}
You need a class for a Mesh which can contain three links to other meshes. You can keep also a list of all meshes but is should be static.
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
}
}
Related
I'm following along a course on udemy which is for free it's a memory game (https://www.udemy.com/xamarin-native-ios-memory-game-csharp/learn/v4/overview)
Now with the randomizer method i get a new problem with the same out of range error
using System;
using System.Collections;
using System.Collections.Generic;
using UIKit;
namespace iOSMemoryGame
{
public partial class ViewController : UIViewController
{
#region vars
List<String> imgArr = new List<String>();
float gameViewWidth;
int gridSize = 6;
ArrayList tilesArr = new ArrayList();
ArrayList coordsArr = new ArrayList();
#endregion
public ViewController(IntPtr handle) : base(handle)
{
}
public override void ViewDidLoad()
{
base.ViewDidLoad();
// Perform any additional setup after loading the view, typically from a nib.
}
public override void ViewDidAppear(bool animated)
{
base.ViewDidAppear(animated);
// make sure Game View is Laid Out
gameView.LayoutIfNeeded();
gameViewWidth = (float)gameView.Frame.Size.Width;
// let's load all of our images into an array
for (int i = 1; i <= 18; i++)
{
imgArr.Add("img_" + i.ToString() + ".png");
}
// let's make a call to tileMaker
tileMaker();
// let's call the randomizer
randomizer();
}
private void randomizer()
{
// we are gonna go through our tiles in ORDER
// and we are gonna assign a new center to them RANDOMLY
foreach (UIView any in tilesArr)
{
// UIImageView thisTile = (UIImageView)tilesArr[i];
Random myRand = new Random();
int randomIndex = myRand.Next(0, coordsArr.Count);
CoreGraphics.CGPoint newRandCenter = (CoreGraphics.CGPoint)coordsArr[randomIndex];
any.Center = newRandCenter;
coordsArr.RemoveAt(randomIndex);
}
}
private void tileMaker()
{
float tileWidth = gameViewWidth / gridSize;
float xCenter = tileWidth / 2;
float yCenter = tileWidth / 2;
int imgCounter = 0;
for (int h = 0; h < gridSize; h++)
{
for (int v = 0; v < gridSize; v++)
{
UIImageView tileImgView = new UIImageView();
CoreGraphics.CGPoint newCenter = new CoreGraphics.CGPoint(xCenter, yCenter);
tileImgView.Frame = new CoreGraphics.CGRect(0, 0, tileWidth - 5, tileWidth - 5);
String imgName = imgArr[imgCounter];
tileImgView.Image = new UIImage(imgName);
tileImgView.Center = newCenter;
// user CAN interact with this image view
tileImgView.UserInteractionEnabled = true;
// adding the new image view to the array
tilesArr.Add(tileImgView);
gameView.AddSubview(tileImgView);
xCenter = xCenter + tileWidth;
imgCounter++;
if (imgCounter == gridSize * gridSize / 2)
{
imgCounter = 0;
}
}
xCenter = tileWidth / 2;
yCenter = yCenter + tileWidth;
}
}
public override void DidReceiveMemoryWarning()
{
base.DidReceiveMemoryWarning();
// Release any cached data, images, etc that aren't in use.
}
partial void Rst4Button_TouchUpInside(UIButton sender)
{
throw new NotImplementedException();
}
partial void Rst6Button_TouchUpInside(UIButton sender)
{
throw new NotImplementedException();
}
}
}
Something is wrong with the randomizer method but i dont know what.
it gives me again a out of range error.
without the randomizer method it works fine
This line
for (int i = 1; i < 18; i++)
creates 17 images, not 18 as expected by the following loops.
// 0-5 = 6 loops
for (int h = 0; h < gridSize; h++)
{
// 0-5 = 6 loops (h*v=18)
for (int v = 0; v < gridSize; v++)
{
....
You need to write
for (int i = 0; i < 18; i++)
imgArr.Add("img_" + (i+1).ToString() + ".png");
I've been working on building a procedural generator for Unity, that takes in noise and uses it to build a height map.
So far, everything seems to work as long as I limit the size of the mesh to around 250x250. If I attempt to make a larger mesh, the script won't calculate it.
The puzzling thing is that I get no memory errors or anything of that nature. I've implemented a Regenerate button that allows me to generate a new mesh in Unity and as long as I remain in the range of 250x250 or less, it works fine. If I pick a larger value, the mesh simply remains unchanged.
How I calculate the Mesh:
using UnityEngine;
using System.Collections;
using UnityEditor;
using System.IO;
[ExecuteInEditMode]
[RequireComponent(typeof(MeshFilter))]
[RequireComponent(typeof(Noise))]
public class CustomTerrain : MonoBehaviour {
//Note: sizeX*sizeZ determines mesh size.
public int sizeX = 4; //These values are public so they can be
public int sizeZ = 4; //modified in the Unity Editor.
public float noiseSize = 1.0f;
public float cellSize = 1.0f;
private string mPath = "Assets/Generated/";
Noise noise;
void Start() {
noise = GetComponent<Noise>();
this.LoadMesh();
if (!GetComponent<MeshFilter>().sharedMesh) {
this.Regenerate();
}
}
public void LoadMesh() {
Mesh mesh = Instantiate(AssetDatabase.LoadMainAssetAtPath(mPath + gameObject.name + ".asset") as Mesh);
if (mesh) {
GetComponent<MeshFilter>().mesh = mesh;
}
recalculateMeshCollider(mesh);
}
Vector3[] GenVertices() {
float x, z;
int w = (sizeX+1);
int l = (sizeZ+1);
Vector3[] vertices = new Vector3[w*l];
for (int gx = 0; gx < w; gx++) {
for (int gz = 0; gz < l; gz++) {
x = gx*cellSize;
z = gz*cellSize;
float height = (noiseSize * noise.Get(x,z));
vertices[gx*l+gz] = new Vector3(x, height, z);
}
}
return vertices;
}
int[] GenTriangles() {
int vertciesPerTriangle = 3;
int trianglesPerCell = 2;
int numberCells = sizeX * sizeZ;
int[] triangles = new int[vertciesPerTriangle * trianglesPerCell * numberCells];
int tIndeX = 0;
for (int cX = 0; cX < sizeX; cX++) {
for (int cZ = 0; cZ < sizeZ; cZ++) {
int n = cX*(sizeZ+1)+cZ;
triangles[tIndeX] = n;
triangles[tIndeX+1] = n+1;
triangles[tIndeX+2] = n+sizeZ+2;
triangles[tIndeX+3] = n;
triangles[tIndeX+4] = n+sizeZ+2;
triangles[tIndeX+5] = n+sizeZ+1;
tIndeX +=6;
}
}
return triangles;
}
Vector2[] GenUVs() {
int w = (sizeX + 1);
int l = (sizeZ + 1);
Vector2[] uvs = new Vector2[w * l];
for (int uX = 0; uX < w; uX++) {
for (int uZ = 0; uZ < l; uZ++) {
uvs[uX*l+uZ] = new Vector2((float)uX/sizeX, (float)uZ/sizeZ);
}
}
return uvs;
}
}
My Regenerate function:
public void Regenerate() {
noise.Init();
Mesh mesh = GetComponent<MeshFilter>().sharedMesh;
if(!mesh) {
mesh = new Mesh();
GetComponent<MeshFilter>().sharedMesh = mesh;
}
mesh.vertices = GenVertices();
mesh.triangles = GenTriangles();
mesh.uv = GenUVs();
mesh.RecalculateNormals();
recalculateMeshCollider(mesh);
}
public void recalculateMeshCollider(Mesh mesh) {
if (GetComponent<MeshCollider>()) {
DestroyImmediate(GetComponent<MeshCollider>());
}
transform.gameObject.AddComponent<MeshCollider>();
transform.GetComponent<MeshCollider>().sharedMesh = mesh;
}
By "250x250" do you mean there's 62.400 triangles?
Unity has a vertex limit of 65535 count - just use more than one mesh, no trouble.
In my Unity project, I want to have a progress bar that starts loading when I import a .obj model during runtime.
How I want to it work is when I press "spacebar", the ObjImporter would start importing/drawing the assigned model and during that period of time while it's drawing, there would be a progress bar somewhere that shows the completion of the importing+/drawing progress, so the user could see the estimated amount of time neededto complete and not get impatient.
I'm using a slightly modified ObjImporter.cs from unity wiki:
/* This version of ObjImporter first reads through the entire file, getting a count of how large
* the final arrays will be, and then uses standard arrays for everything (as opposed to ArrayLists
* or any other fancy things).
*/
using UnityEngine;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using System.Text;
public class ObjImporter : MonoBehaviour {
public GameObject spawnPoint;
public GameObject emptyPrefabWithMeshRenderer;
public string meshPath;
public GameObject spawnedPrefab;
public float progressPercentage;
int noOfLines;
void Start ()
{
progressPercentage = 0;
}
void Update ()
{
if(Input.GetKeyDown("space")){
Mesh importedMesh = GetComponent<ObjImporter>().ImportFile(meshPath);
noOfLines = TotalLines(meshPath);
spawnedPrefab=Instantiate(emptyPrefabWithMeshRenderer,spawnPoint.transform.position,spawnPoint.transform.rotation) as GameObject;
spawnedPrefab.GetComponent<MeshFilter>().mesh=importedMesh;
spawnedPrefab.GetComponent<Renderer>().material.color = new Color(Random.value, Random.value, Random.value, 1.0f);
}
}
private struct meshStruct
{
public Vector3[] vertices;
public Vector3[] normals;
public Vector2[] uv;
public Vector2[] uv1;
public Vector2[] uv2;
public int[] triangles;
public int[] faceVerts;
public int[] faceUVs;
public Vector3[] faceData;
public string name;
public string fileName;
}
// Use this for initialization
public Mesh ImportFile (string filePath){
meshStruct newMesh = createMeshStruct(filePath);
populateMeshStruct(ref newMesh);
Vector3[] newVerts = new Vector3[newMesh.faceData.Length];
Vector2[] newUVs = new Vector2[newMesh.faceData.Length];
Vector3[] newNormals = new Vector3[newMesh.faceData.Length];
int i = 0;
/* The following foreach loops through the facedata and assigns the appropriate vertex, uv, or normal
* for the appropriate Unity mesh array.
*/
foreach (Vector3 v in newMesh.faceData)
{
newVerts[i] = newMesh.vertices[(int)v.x - 1];
if (v.y >= 1)
newUVs[i] = newMesh.uv[(int)v.y - 1];
if (v.z >= 1)
newNormals[i] = newMesh.normals[(int)v.z - 1];
i++;
}
Mesh mesh = new Mesh();
mesh.vertices = newVerts;
mesh.uv = newUVs;
mesh.normals = newNormals;
mesh.triangles = newMesh.triangles;
mesh.RecalculateBounds();
mesh.Optimize ();
return mesh;
}
private int TotalLines(string filePath)
{
using (StreamReader r = new StreamReader(filePath))
{
int i = 0;
while (r.ReadLine() != null)
{
i++;
}
return i;
}
}
private static meshStruct createMeshStruct(string filename)
{
int triangles = 0;
int vertices = 0;
int vt = 0;
int vn = 0;
int face = 0;
meshStruct mesh = new meshStruct();
mesh.fileName = filename;
// Read and retrieve all the text in the file.
StreamReader stream = File.OpenText(filename);
string entireText = stream.ReadToEnd();
stream.Close(); // End of stream.
// Going through the retrieved text.
using (StringReader reader = new StringReader(entireText))
{
string currentText = reader.ReadLine();
char[] splitIdentifier = { ' ' };
string[] brokenString;
while (currentText != null)
{
if (!currentText.StartsWith("f ") && !currentText.StartsWith("v ") && !currentText.StartsWith("vt ")
&& !currentText.StartsWith("vn "))
{
currentText = reader.ReadLine();
if (currentText != null)
{
currentText = currentText.Replace(" ", " ");
}
}
else
{
currentText = currentText.Trim(); // Trim the current line
brokenString = currentText.Split(splitIdentifier, 50); // Split the line into an array, separating the original line by blank spaces
switch (brokenString[0])
{
case "v":
vertices++;
break;
case "vt":
vt++;
break;
case "vn":
vn++;
break;
case "f":
face = face + brokenString.Length - 1;
triangles = triangles + 3 * (brokenString.Length - 2); /*brokenString.Length is 3 or greater since a face must have at least
3 vertices. For each additional vertice, there is an additional
triangle in the mesh (hence this formula).*/
break;
}
currentText = reader.ReadLine();
if (currentText != null)
{
currentText = currentText.Replace(" ", " ");
}
}
}
}
mesh.triangles = new int[triangles];
mesh.vertices = new Vector3[vertices];
mesh.uv = new Vector2[vt];
mesh.normals = new Vector3[vn];
mesh.faceData = new Vector3[face];
return mesh;
}
private static void populateMeshStruct(ref meshStruct mesh)
{
StreamReader stream = File.OpenText(mesh.fileName);
string entireText = stream.ReadToEnd();
stream.Close();
using (StringReader reader = new StringReader(entireText))
{
string currentText = reader.ReadLine();
char[] splitIdentifier = { ' ' };
char[] splitIdentifier2 = { '/' };
string[] brokenString;
string[] brokenBrokenString;
int f = 0;
int f2 = 0;
int v = 0;
int vn = 0;
int vt = 0;
int vt1 = 0;
int vt2 = 0;
while (currentText != null)
{
if (!currentText.StartsWith("f ") && !currentText.StartsWith("v ") && !currentText.StartsWith("vt ") &&
!currentText.StartsWith("vn ") && !currentText.StartsWith("g ") && !currentText.StartsWith("usemtl ") &&
!currentText.StartsWith("mtllib ") && !currentText.StartsWith("vt1 ") && !currentText.StartsWith("vt2 ") &&
!currentText.StartsWith("vc ") && !currentText.StartsWith("usemap "))
{
currentText = reader.ReadLine();
if (currentText != null)
{
currentText = currentText.Replace(" ", " ");
}
}
else
{
currentText = currentText.Trim();
brokenString = currentText.Split(splitIdentifier, 50);
switch (brokenString[0])
{
case "g":
break;
case "usemtl":
break;
case "usemap":
break;
case "mtllib":
break;
case "v":
mesh.vertices[v] = new Vector3(System.Convert.ToSingle(brokenString[1]), System.Convert.ToSingle(brokenString[2]),
System.Convert.ToSingle(brokenString[3]));
v++;
break;
case "vt":
mesh.uv[vt] = new Vector2(System.Convert.ToSingle(brokenString[1]), System.Convert.ToSingle(brokenString[2]));
vt++;
break;
case "vt1":
mesh.uv[vt1] = new Vector2(System.Convert.ToSingle(brokenString[1]), System.Convert.ToSingle(brokenString[2]));
vt1++;
break;
case "vt2":
mesh.uv[vt2] = new Vector2(System.Convert.ToSingle(brokenString[1]), System.Convert.ToSingle(brokenString[2]));
vt2++;
break;
case "vn":
mesh.normals[vn] = new Vector3(System.Convert.ToSingle(brokenString[1]), System.Convert.ToSingle(brokenString[2]),
System.Convert.ToSingle(brokenString[3]));
vn++;
break;
case "vc":
break;
case "f":
int j = 1;
List<int> intArray = new List<int>();
while (j < brokenString.Length && ("" + brokenString[j]).Length > 0)
{
Vector3 temp = new Vector3();
brokenBrokenString = brokenString[j].Split(splitIdentifier2, 3); //Separate the face into individual components (vert, uv, normal)
temp.x = System.Convert.ToInt32(brokenBrokenString[0]);
if (brokenBrokenString.Length > 1) //Some .obj files skip UV and normal
{
if (brokenBrokenString[1] != "") //Some .obj files skip the uv and not the normal
{
temp.y = System.Convert.ToInt32(brokenBrokenString[1]);
}
temp.z = System.Convert.ToInt32(brokenBrokenString[2]);
}
j++;
mesh.faceData[f2] = temp;
intArray.Add(f2);
f2++;
}
j = 1;
while (j + 2 < brokenString.Length) //Create triangles out of the face data. There will generally be more than 1 triangle per face.
{
mesh.triangles[f] = intArray[0];
f++;
mesh.triangles[f] = intArray[j];
f++;
mesh.triangles[f] = intArray[j+1];
f++;
j++;
}
break;
}
currentText = reader.ReadLine();
if (currentText != null)
{
currentText = currentText.Replace(" ", " "); //Some .obj files insert double spaces, this removes them.
}
}
}
}
}
void OnGUI()
{
GUI.Label (new Rect (20, 20, 100, 100), noOfLines.ToString());
}
}
This is a simple ProgressBar.cs I wrote:
using UnityEngine;
using System.Collections;
public class ProgressBar : MonoBehaviour {
float progress;
Vector2 pos;
Vector2 size;
public Texture2D barBG;
public Texture2D barLoad;
// Use this for initialization
void Start () {
progress = 0;
pos = new Vector2 (20, 40);
size = new Vector2 (100, 10);
}
// Update is called once per frame
void Update () {
progress = Time.time * 0.05f; // Place holder.
}
void OnGUI ()
{
GUI.DrawTexture(new Rect(pos.x, pos.y, size.x, size.y), barBG);
GUI.DrawTexture(new Rect(pos.x, pos.y, size.x * Mathf.Clamp01(progress), size.y), barLoad);
}
}
I have looked everywhere for a method in finding out progress completion of file reading+drawing of mesh and couldn't find one.
I've tried having the progressBar load respectively to the number of lines in the .obj file, but it isn't working too well as reading is way faster than the actual drawing of the mesh.
I'm out of ideas, anyone know of any way? Thanks in advance!
Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 8 years ago.
Improve this question
I'm trying to draw an image in my Windows Form Application. I drew instead of the picture some rectangles but I want to replace them somehow with a certain image.
I added the whole code and the problem is in the draw function. Can anybody help?
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 System.Threading;
using System.Drawing.Drawing2D;
using Microsoft.Win32;
namespace kiralyno
{
public partial class Form2 : Form
{
public static int p = 1;
public static int o = 1;
public float[] x1 = new float[80000];
public float[] y1 = new float[80000];
public string hely = " ";
public int db = 0;
public int[] v = new int[80000];
public static string a;
public string s = " ";
public static int n = Form1.n;
public float x = 0, y = 0, w = 450 / n, h = 450 / n;
public int helyes(int i, int k)
{
for (int j = 1; j <= k - 1; j++)
if ((v[j] == i) || (Math.Abs(k - j) == Math.Abs(i - v[j])))
return 0;
return 1;
}
public void kiir(int k)
{
for (int j = 1; j <= k; j++)
{
s += Convert.ToString(v[j]);
if (j != n) s += " ";
}
a = s;
megoldas.Items.Add(a);
s = "";
a = "";
}
public void back(int k)
{
for (int i = 1; i <= n; i++)
{
if (helyes(i, k) == 1)
{
v[k] = i;
if (k == n)
{
kiir(k);
draw();
Thread.Sleep(500);
sakktabla(0, 0, w, h);
db++;
}
else back(k + 1);
}
}
}
public void draw()
{
// Image newImage = Image.FromFile("D:/Akos/Visual/Projects/kiralyno/kir.png");
Graphics g = panel1.CreateGraphics();
for (int m = 1; m <= n; m++)
{
g.DrawRectangle(new Pen(Brushes.Blue), x1[v[m]], y1[m], w, h);
g.FillRectangle(Brushes.Blue, x1[v[m]], y1[m], w, h);
Thread.Sleep(200);
}
}
public Form2()
{
InitializeComponent();
}
public void sakktabla(float x, float y, float w, float h)
{
for (int i = 1; i <= n; i++)
{
for (int j = 1; j <= n; j++)
{
if ((i + j) % 2 == 0)
{
Graphics g = panel1.CreateGraphics();
g.DrawRectangle(new Pen(Brushes.Black), x, y, w, h);
g.FillRectangle(Brushes.Black, x, y, w, h);
x1[p] = x;
x = x + 450 / n;
}
else
{
Graphics g = panel1.CreateGraphics();
g.DrawRectangle(new Pen(Brushes.White), x, y, w, h);
g.FillRectangle(Brushes.White, x, y, w, h);
x1[p] = x;
x = x + 450 / n;
}
p++;
}
y1[o] = y;
for (int m = 1; m <= n; m++)
{
y1[n * m + o] = y1[o];
}
o++;
y = y + 450 / n;
x = 0;
}
}
private void panel1_Paint(object sender, PaintEventArgs e)
{
sakktabla(0, 0, w, h);
}
private void Form2_Deactivate(object sender, EventArgs e)
{
Application.Exit();
}
private void megoldas_Click(object sender, EventArgs e)
{
label1.Text = "";
back(1);
if (db == 0) megoldas.Items.Add("Nincs megoldas!");
string c = Convert.ToString(db);
megoldas.Items.Add(c+" db megoldas van");
megoldas.Enabled = false;
}
private void label1_Click(object sender, EventArgs e)
{
label1.Text = "";
back(1);
if (db == 0) megoldas.Items.Add("Nincs megoldas!");
string c = Convert.ToString(db);
megoldas.Items.Add(c + " db megoldas van");
megoldas.Enabled = false;
}
private void pictureBox1_Click(object sender, EventArgs e)
{
}
}
}
Source: http://msdn.microsoft.com/en-us/library/yws82c40%28v=vs.110%29.aspx
private void DrawImageRect(PaintEventArgs e)
{
// Create image.
Image newImage = Image.FromFile("SampImag.jpg");
// Create rectangle for displaying image.
Rectangle destRect = new Rectangle(100, 100, 450, 150);
// Draw image to screen.
e.Graphics.DrawImage(newImage, destRect);
}
If you really need to draw it yourself, use: DrawImage.
In general it's usually easier to use a PictureBox, though.
I'm trying to make a drag and drop from an array of object. At first, they will copied in another array. But, when i try to updating the original array, the copy has updating too.
here my codes:
namespace drop_test2
{
public class Game1 : Microsoft.Xna.Framework.Game
{
GraphicsDeviceManager graphics;
SpriteBatch spriteBatch;
InputManager input;
Texture2D texure;
DragableObject[] dragObjects, copyDragObjects;
public Game1()
{
graphics = new GraphicsDeviceManager(this);
Content.RootDirectory = "Content";
this.IsMouseVisible = true;
this.input = new InputManager(this);
this.dragObjects = new DragableObject[6 * 6];
}
protected override void LoadContent()
{
this.spriteBatch = new SpriteBatch(this.GraphicsDevice);
this.input.Load();
this.texure = new Texture2D(this.GraphicsDevice, 50, 50, false, SurfaceFormat.Color);
Color[] c = new Color[this.texure.Width * this.texure.Height];
for (int i = 0; i < c.Length; i++) c[i] = Color.White;
this.texure.SetData(c);
for (int x = 0; x < 6; x++)
{
for (int y = 0; y < 6; y++)
{
var obj = new DragableObject();
obj.Size = new Vector2(50);
obj.Position = new Vector2(35) + new Vector2(x, y) * obj.Size;
this.dragObjects[x + y * 6] = obj;
}
}
this.copyDragObjects = this.dragObjects;
}
protected override void Update(GameTime gameTime)
{
this.input.Update(gameTime);
for (int i = 0; i < this.dragObjects.Length; i++)
{
if (this.dragObjects[i].CheckHover(input.CurrentCursorPost))
{
this.copyDragObjects[i].Position += new Vector2(.5f, 0);
}
}
}
Color c = Color.Blue;
protected override void Draw(GameTime gameTime)
{
this.GraphicsDevice.Clear(Color.CornflowerBlue);
this.spriteBatch.Begin();
for (int x = 0; x < 6; x++)
{
for (int y = 0; y < 6; y++)
{
if ((x + y) % 2 == 0)
c = Color.DarkGreen;
else
c = Color.LightGreen;
if (this.dragObjects[x + y * 6].IsHover)
c = Color.DarkOrchid * .5f;
if (this.dragObjects[x + y * 6].IsSelected)
c = Color.DarkRed * .75f;
this.spriteBatch.Draw(this.texure, this.dragObjects[x + y * 6].Position, null, c,
0f, new Vector2(texure.Width, texure.Height) * .5f, 1f, SpriteEffects.None, 0);
}
}
this.spriteBatch.End();
}
}
}
this is the dragableobject class
namespace drop_test2
{
struct DragableObject
{
public Vector2 Position
{
get;
set;
}
public Vector2 Size
{
get;
set;
}
public bool IsSelected
{
get;
set;
}
public bool IsHover
{
get;
set;
}
public bool CheckHover(Vector2 vector2)
{
Rectangle r = new Rectangle((int)(this.Position.X - this.Size.X * .5), (int)(this.Position.Y - this.Size.Y * .5f),
(int)this.Size.X, (int)this.Size.Y);
if (r.Contains((int)vector2.X,(int)vector2.Y))
{
this.IsHover = true;
return true;
}
this.IsHover = false;
return false;
}
}
}
Anyone wanna help me to solving this problem?
If you use CopyTo() c# internally refers to the original array. If you want to create a new instance you have to use Clone().
Example:
object[] src = { "a", "b" };
var dest = src.Clone() as object[];
src[0] = "c";
//// dest still contains "a","b"
Also see: Difference between the System.Array.CopyTo() and System.Array.Clone()