Hello i really need help. i am using unity and i have this code to export obj. but i also wantmy obj to contain textures. i can export texture as jpg but i do not want it, i need mtl file. i want obj to have that textures with it and not with jpg.so how can i make mtl for my exported obj file?
using System.Collections;
using System.IO;
using System.Text;
using System;
public class ObjExporter
{
public static string MeshToString(MeshFilter mf)
{
Mesh m = mf.mesh;
Material[] mats = mf.GetComponent<Renderer>().sharedMaterials;
StringBuilder sb = new StringBuilder();
//sb.Append("g ").Append(mf.name).Append("\n");
foreach (Vector3 v in m.vertices)
{
sb.Append(string.Format("v {0} {1} {2}\n", v.x, v.y, v.z));
}
sb.Append("\n");
foreach (Vector3 v in m.normals)
{
sb.Append(string.Format("vn {0} {1} {2}\n", v.x, v.y, v.z));
}
sb.Append("\n");
foreach (Vector3 v in m.uv)
{
sb.Append(string.Format("vt {0} {1}\n", v.x, v.y));
}
for (int material = 0; material < m.subMeshCount; material++)
{
sb.Append("\n");
sb.Append("usemtl ").Append(mats[material].name).Append("\n");
sb.Append("usemap ").Append(mats[material].name).Append("\n");
int[] triangles = m.GetTriangles(material);
for (int i = 0; i < triangles.Length; i += 3)
{
sb.Append(string.Format("f {0}/{0}/{0} {1}/{1}/{1} {2}/{2}/{2}\n",
triangles[i] + 1, triangles[i + 1] + 1, triangles[i + 2] + 1));
}
}
return sb.ToString();
}
public static void MeshToFile(MeshFilter mf, string filename)
{
using (StreamWriter sw = new StreamWriter(filename))
{
sw.Write(MeshToString(mf));
string path = Application.dataPath + "/screenshots/" + DateTime.Now.ToString("yyyy-MM-dd HH-mm-ss") + ".png";
}
}
}
Related
Hi I need to create a list in .txt but using these codes I am only able to write data and keying anymore will just overwrite the first one
int score = Convert.ToInt32(ScoreLBL.Text);
String name = NameTB.Text;
List<Leaderboard> LB = new List<Leaderboard>();
Leaderboard results;
results = new Leaderboard(name, score);
LB.Add(results);
StreamWriter sw = new StreamWriter(#"C:\Users\zxong\Desktop\EGL138-OBJECT-ORIENTED PROGRAMMING\Project\Leaderboard.txt");
for (int i = 0; i< LB.Count(); i++)
{
sw.WriteLine(LB[i].getName() + "," + LB[i].getScore());
}
Leaderboard class
class Leaderboard
{
private String name;
protected int score;
public Leaderboard(String n, int s)
{
this.name = n;
this.score = s;
}
public String getName()
{
return this.name;
}
public int getScore()
{
return this.score;
}
}
i think this small change should be able to give you the functionality you want:
List<Leaderboard> LB = new List<Leaderboard>();
LB.Add(new Leaderboard("SomeName", 10));
LB.Add(new Leaderboard("AnotherName", 20));
LB.Add(new Leaderboard("ThirdName", 30));
using (StreamWriter sw = new StreamWriter(#"C:\Users\zxong\Desktop\EGL138-OBJECT-ORIENTED PROGRAMMING\Project\Leaderboard.txt", true)) {
for (int i = 0; i < LB.Count; i++) {
//Console.WriteLine(LB[i].getName() + "," + LB[i].getScore());
sw.WriteLine(LB[i].getName() + "," + LB[i].getScore());
}
}
Adding the true flag at the end of the StreamWriter should set the stream writer to work in append mode, which should add new lines rather than overwrite them on the file.
I have an array with binary values which I exploded it and inserted them into an array, but now I want to move this elements into an [8, 8] matrix (line-per-line), how may I do this?
I've been trying but I couldn't find any good example
static void Main(string[] args)
{
string textonorm, textobin = "", textobin1 = "", textocod = "";
int textval, quant, result, txtvalor;
Console.WriteLine("Digite a frase que deseja criptografar!");
textonorm = Console.ReadLine();
textval = System.Text.ASCIIEncoding.UTF8.GetByteCount(textonorm);
byte[] phrase = Encoding.ASCII.GetBytes(textonorm);
foreach (byte b in phrase)
{
textobin += Convert.ToString(b, 2);
textval = textobin.Length;
}
if (textval < 64)
{
quant = 64 - textval;
foreach (byte b in phrase)
{
textobin1 += Convert.ToString(b, 2);
}
textocod = textobin1.PadLeft(quant, '0');
txtvalor = textobin1.Length;
Console.WriteLine(textocod.ToString() + "\r\n " + "\r\n " + txtvalor.ToString());
string[] textarray = textocod.Split('0', '1');
int[,] matrizval = new int[8,8];
foreach (var substr in textarray)
{
Console.WriteLine(Convert.ToString());
}
}
else
{
Console.WriteLine("ok");
}
}
The code could be improved if you explain exactly what you expect of it, but to copy the values to the matrix:
using System;
using System.Text;
namespace ConsoleApplication
{
class Program
{
static void Main(string[] args)
{
string textonorm, textobin = "", textobin1 = "", textocod = "";
int textval, quant, result, txtvalor;
Console.WriteLine("Digite a frase que deseja criptografar!");
textonorm = Console.ReadLine();
textval = System.Text.ASCIIEncoding.UTF8.GetByteCount(textonorm);
byte[] phrase = Encoding.ASCII.GetBytes(textonorm);
foreach (byte b in phrase)
{
textobin += Convert.ToString(b, 2);
textval = textobin.Length;
}
if (textval < 64)
{
quant = 64;
foreach (byte b in phrase)
{
textobin1 += Convert.ToString(b, 2);
}
textocod = textobin1.PadLeft(quant, '0');
txtvalor = textobin1.Length;
Console.WriteLine(textocod.ToString() + "\r\n " + "\r\n " + txtvalor.ToString());
char[] chararray = textocod.ToCharArray();
int[,] matrizval = new int[8, 8];
if (chararray.Length == 64)
for (int i = 0; i < 8; ++i)
{
for (int j = 0; j < 8; ++j)
{
int val = chararray[i * 8 + j] - '0';
Console.Write(val);
matrizval[i, j] = val;
}
Console.WriteLine();
}
}
else
{
Console.WriteLine("ok");
}
Console.Write("\nPress any key...");
Console.ReadKey();
}
}
}
UnityEditor it is only meant to work in the Editor only, but I need to use a similar feature in the playing mode.
ObjMaterial objMaterial = new ObjMaterial();
objMaterial.name = mats[material].name;
objMaterial.textureName = AssetDatabase.GetAssetPath(mats[material].mainTexture);
materialList.Add(objMaterial.name, objMaterial);
Full code:
\\\\\\\\\\\\\\\\\\\
using UnityEngine;
using UnityEditor;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using System.Text;
using System;
using System.Linq;
struct ObjMaterial
{
public string name;
public string textureName;
}
public class Menu : MonoBehaviour {
public int window;
void Start () {
window = 1;
}
private static int vertexOffset = 0;
private static int normalOffset = 0;
private static int uvOffset = 0;
private static string targetFolder = "ExportedObj";
private static string MeshToString(Component mf, Dictionary<string, ObjMaterial> materialList)
{
Mesh m;
Material[] mats;
if(mf is MeshFilter)
{
m = (mf as MeshFilter).mesh;
mats = mf.GetComponent<Renderer>().sharedMaterials;
}
else if(mf is SkinnedMeshRenderer)
{
m = (mf as SkinnedMeshRenderer).sharedMesh;
mats = (mf as SkinnedMeshRenderer).sharedMaterials;
}
else
{
return "";
}
StringBuilder sb = new StringBuilder();
sb.Append("g ").Append(mf.name).Append("\n");
foreach(Vector3 lv in m.vertices)
{
Vector3 wv = mf.transform.TransformPoint(lv);
sb.Append(string.Format("v {0} {1} {2}\n",-wv.x,wv.y,wv.z));
}
sb.Append("\n");
foreach(Vector3 lv in m.normals)
{
Vector3 wv = mf.transform.TransformDirection(lv);
sb.Append(string.Format("vn {0} {1} {2}\n",-wv.x,wv.y,wv.z));
}
sb.Append("\n");
foreach(Vector3 v in m.uv)
{
sb.Append(string.Format("vt {0} {1}\n",v.x,v.y));
}
for (int material=0; material < m.subMeshCount; material ++) {
sb.Append("\n");
sb.Append("usemtl ").Append(mats[material].name).Append("\n");
sb.Append("usemap ").Append(mats[material].name).Append("\n");
//See if this material is already in the materiallist.
try
{
ObjMaterial objMaterial = new ObjMaterial();
objMaterial.name = mats[material].name;
objMaterial.textureName = EditorUtility.GetAssetPath(mats[material].mainTexture);
//else
//objMaterial.textureName = null;
materialList.Add(objMaterial.name, objMaterial);
}
catch (ArgumentException)
{
//Already in the dictionary
}
int[] triangles = m.GetTriangles(material);
for (int i=0;i<triangles.Length;i+=3)
{
//Because we inverted the x-component, we also needed to alter the triangle winding.
sb.Append(string.Format("f {1}/{1}/{1} {0}/{0}/{0} {2}/{2}/{2}\n",
triangles[i]+1 + vertexOffset, triangles[i+1]+1 + normalOffset, triangles[i+2]+1 + uvOffset));
}
}
vertexOffset += m.vertices.Length;
normalOffset += m.normals.Length;
uvOffset += m.uv.Length;
return sb.ToString();
}
private static void Clear()
{
vertexOffset = 0;
normalOffset = 0;
uvOffset = 0;
}
private static Dictionary<string, ObjMaterial> PrepareFileWrite()
{
Clear();
return new Dictionary<string, ObjMaterial>();
}
private static void MaterialsToFile(Dictionary<string, ObjMaterial> materialList, string folder, string filename)
{
using (StreamWriter sw = new StreamWriter(folder + "/" + filename + ".mtl"))
{
foreach( KeyValuePair<string, ObjMaterial> kvp in materialList )
{
sw.Write("\n");
sw.Write("newmtl {0}\n", kvp.Key);
sw.Write("Ka 0.6 0.6 0.6\n");
sw.Write("Kd 0.6 0.6 0.6\n");
sw.Write("Ks 0.9 0.9 0.9\n");
sw.Write("d 1.0\n");
sw.Write("Ns 0.0\n");
sw.Write("illum 2\n");
if (kvp.Value.textureName != null)
{
string destinationFile = kvp.Value.textureName;
int stripIndex = destinationFile.LastIndexOf('/');//FIXME: Should be Path.PathSeparator;
if (stripIndex >= 0)
destinationFile = destinationFile.Substring(stripIndex + 1).Trim();
string relativeFile = destinationFile;
destinationFile = folder + "/" + destinationFile;
Debug.Log("Copying texture from " + kvp.Value.textureName + " to " + destinationFile);
try
{
//Copy the source file
File.Copy(kvp.Value.textureName, destinationFile);
}
catch
{
}
sw.Write("map_Kd {0}", relativeFile);
}
sw.Write("\n\n\n");
}
}
}
private static void MeshToFile(Component mf, string folder, string filename)
{
Dictionary<string, ObjMaterial> materialList = PrepareFileWrite();
using (StreamWriter sw = new StreamWriter(folder +"/" + filename + ".obj"))
{
sw.Write("mtllib ./" + filename + ".mtl\n");
sw.Write(MeshToString(mf, materialList));
}
MaterialsToFile(materialList, folder, filename);
}
private static void MeshesToFile(Component[] mf, string folder, string filename)
{
Dictionary<string, ObjMaterial> materialList = PrepareFileWrite();
using (StreamWriter sw = new StreamWriter(folder +"/" + filename + ".obj"))
{
sw.Write("mtllib ./" + filename + ".mtl\n");
for (int i = 0; i < mf.Length; i++)
{
sw.Write(MeshToString(mf[i], materialList));
}
}
MaterialsToFile(materialList, folder, filename);
}
private static bool CreateTargetFolder()
{
try
{
System.IO.Directory.CreateDirectory(targetFolder);
}
catch
{
return false;
}
return true;
}
void OnGUI () {
GUI.BeginGroup (new Rect (Screen.width / 2 - 100, Screen.height / 2 - 100, 200, 200));
if(window == 1)
{
if(GUI.Button (new Rect (10,30,180,30), "Экспортировать"))
{
if (!CreateTargetFolder())
return;
GameObject[] selection = GameObject.FindGameObjectsWithTag("Boat");
if (selection.Length == 0)
{
//EditorUtility.DisplayDialog("No source object selected!", "Please select one or more target objects", "");
return;
}
int exportedObjects = 0;
ArrayList mfList = new ArrayList();
for (int i = 0; i < selection.Length; i++)
{
Component[] meshfilter = selection[i].GetComponentsInChildren(typeof(MeshFilter)).Concat(selection[i].GetComponentsInChildren(typeof(SkinnedMeshRenderer))).ToArray();
for (int m = 0; m < meshfilter.Length; m++)
{
exportedObjects++;
mfList.Add(meshfilter[m]);
}
}
if (exportedObjects > 0)
{
Component[] mf = new Component[mfList.Count];
for (int i = 0; i < mfList.Count; i++) {
mf [i] = (Component)mfList [i];
}
string filename = /*EditorApplication.currentScene +*/ "_" + exportedObjects;
int stripIndex = filename.LastIndexOf ('/');//FIXME: Should be Path.PathSeparator
if (stripIndex >= 0)
filename = filename.Substring (stripIndex + 1).Trim ();
MeshesToFile (mf, targetFolder, filename);
}
}
if(GUI.Button (new Rect (10,150,180,30), "Выход"))
{
window = 5;
}
}
if(window == 5)
{
GUI.Label(new Rect(50, 10, 180, 30), "Вы уже выходите?");
if(GUI.Button (new Rect (10,40,180,30), "Да"))
{
Application.Quit();
}
if(GUI.Button (new Rect (10,80,180,30), "Нет"))
{
window = 1;
}
}
GUI.EndGroup ();
}
}
I have looked up about threadpooling and etc and found an example of it. At the moment was i trying to recreate the example i saw for my own project and i keep getting this error when i input any number from the UI.
ManualResetEvent[] doneReadEvents = new ManualResetEvent[Read];
ManualResetEvent[] doneWriteEvents = new ManualResetEvent[Write];
ReadWrite[] ReadArray = new ReadWrite[Read];
ReadWrite[] WriteArray = new ReadWrite[Write];
for (int i = 0; i < Read; i++)
{
doneReadEvents[i] = new ManualResetEvent(false);
ReadWrite Rw = new ReadWrite(Read, doneReadEvents[i]);
ReadArray[i] = Rw;
ThreadPool.QueueUserWorkItem(Rw.ThreadPoolCallBackRead, i);
}
for (int i = 0; i < Write; i++)
{
doneReadEvents[i] = new ManualResetEvent(false);
ReadWrite rW = new ReadWrite(Write, doneWriteEvents[i]);
ReadArray[i] = rW;
ThreadPool.QueueUserWorkItem(rW.ThreadPoolCallBackWrite, i);
}
WaitHandle.WaitAny(doneReadEvents);
WaitHandle.WaitAny(doneWriteEvents);
temp.Items.Add("Complete");
temp.Items.Add("Closing");
Output.DataSource = ReadWrite.MyList;
Work.DataSource = ReadWrite.MyList2;
ReadWrite.ReadData(Read);
}
the first line in the first loop i get an error saying it is out of bound of the array. when that error clears i dont know if there will be any more errors
namespace MultiThreadingReaderWriter
{
class ReadWrite
{
public int _rw;
public ManualResetEvent _doneEvents;
public List<string> myList = new List<string>();
public List<string> myList2 = new List<string>();
public List<string> MyList{ get { return myList; } }
public List<string> MyList2{ get { return myList2; } }
public int RW { get { return _rw; } }
//Constructor
public ReadWrite(int rw, ManualResetEvent doneEvents)
{
_rw = rw;
_doneEvents = doneEvents;
}
public void ThreadPoolCallBackRead(Object threadContext)
{
int threadindex = (int) threadContext;
myList.Add("Thread Read " + threadindex+ " started");
ReadData(_rw);
myList.Add("Thread Read " + threadindex + " done");
_doneReadEvents.Set();
}
public void ThreadPoolCallBackWrite(Object threadContext)
{
int threadindex = (int)threadContext;
myList.Add("Thread Write " + threadindex + " started");
WriteData(_rw);
myList.Add("Thread Write " + threadindex + " done");
_doneWriteEvents.Set();
}
public void ReadData(int reader)
{
myList.Add("Reader " + reader + " has entered Critical Section");
myList.Add("Reader " + reader + " is Reading");
myList.Add("Reader " + reader + " is leaving Critical Section");
}
public void WriteData(int writer)
{
myList.Add("Writer " + writer + " has entered Critical Section");
myList.Add("Writer " + writer + " is writing");
myList.Add("Writer " + writer + " is leaving Critical Section");
}
}
}
this is the class connected to that above form program.
Array indices start from zero and the right way to iterate would be
for (int i = 0; i < Read; i++)
{
}
for (int i = 0; i < Write; i++)
{
}
Index was out of range. Must be non-negative and less than the size of the collection.
Parameter name: index
I have the class WireObjectAnimation:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using System.Windows.Forms;
using DannyGeneral;
namespace AnimationEditor
{
class WireObjectAnimation
{
private List<WireObjectCoordinates> wocl = new List<WireObjectCoordinates>();
private WireObject wo1 = null;
string name;
int ndx;
public WireObjectAnimation(string name,WireObject wo)
{
this.name = name;
wo1 = wo;
WireObjectCoordinates woc;
woc = new WireObjectCoordinates(wo.woc);
wocl.Add(woc);
ndx = 0;
}
public void Save(string path , string fileName , PictureBox pb)
{
int framesNumberX = 0;
int framesNumberY = 0;
string fn;
string t = Path.GetFileNameWithoutExtension(this.name);
if (File.Exists(path + "\\" + "DATABASE" + "\\" + fileName + "\\" + t + ".txt"))
{
try
{
string f = Path.Combine(path + "\\" + "DATABASE" + "\\" + t + "\\" + fileName);
File.Delete(f);
}
catch (Exception ex)
{
MessageBox.Show("Error: Could not delete file from disk. Original error: " + ex.Message);
}
fn = path + "\\" + "DATABASE" + "\\" + t + "\\" + fileName;
}
else
{
fn = path + "\\" + "DATABASE" + "\\" + fileName + "\\" + this.name + ".txt";
}
OptionsFile setting_file = new OptionsFile(fn);
setting_file.SetKey("File Name", fn);
setting_file.SetKey("Object Name", fileName);
setting_file.SetKey("Animation Name", this.name);
setting_file.SetKey("picturebox.Width", pb.Width.ToString());
setting_file.SetKey("picturebox.Height", pb.Height.ToString());
string[] xFrames = new string[wocl.Count];
string[] yFrames = new string[wocl.Count];
string X="";
string Y="";
for (int i = 0; i < wocl.Count; i++)
{
X = string.Format("Frame_X_{0} ", i + 1);
Y = string.Format("Frame_Y_{0} ", i + 1);
framesNumberX ++;
framesNumberY ++;
for (int j = 0; j < wocl[i].Point_X.Count; j++)
{
xFrames[i] += string.Format("{0},", wocl[i].Point_X[j]);
yFrames[i] += string.Format("{0},", wocl[i].Point_Y[j]);
}
string tt = xFrames[i].Trim(",".ToCharArray());
string yy = yFrames[i].Trim(",".ToCharArray());
setting_file.SetKey(X, tt);
setting_file.SetKey(Y, yy);
}
int resultX = framesNumberX / 2;
int resultY = framesNumberY / 2;
setting_file.SetKey("Number Of Frames X", resultX.ToString());
setting_file.SetKey("Number Of Frames Y", resultY.ToString());
}
public void Load(string path,string fileName)
{
int numberofframesX = 0;
int numberofframesY = 0;
string framesX = "";
string framesY = "";
string X = "";
string Y = "";
string t = path + "\\" + fileName;
OptionsFile setting_file = new OptionsFile(t);
string XX = setting_file.GetKey("Number Of Frames X");
string YY = setting_file.GetKey("Number Of Frames Y");
numberofframesX = Convert.ToInt32(XX);
numberofframesY = Convert.ToInt32(YY);
for (int i = 1; i < numberofframesX ; i++)
{
X = string.Format("Frame_X_{0} ", i);
framesX = setting_file.GetKey(X);
List<string> floatStrings = new List<string>(framesX.Split(new char[] { ',' }));
List<float> test = floatStrings.Select(tempStr => (float)Convert.ToDouble(tempStr)).ToList();
wo1.woc.Point_X = test;
}
for (int i = 1; i < numberofframesY; i++)
{
Y = string.Format("Frame_Y_{0} ", i);
framesY = setting_file.GetKey(Y);
List<string> floatStrings = new List<string>(framesY.Split(new char[] { ',' }));
List<float> test = floatStrings.Select(tempStr => (float)Convert.ToDouble(tempStr)).ToList();
wo1.woc.Point_Y = test;
}
}
public void SetFrame(int frameNumber, WireObjectCoordinates woc)
{
wocl[frameNumber].Set(woc);
}
public WireObjectCoordinates GetFrame(int frameNumber)
{
if (frameNumber > wocl.Count)
{
throw new Exception("not allowed!");
}
if (frameNumber == wocl.Count)
{
WireObjectCoordinates woc;
woc = new WireObjectCoordinates(wocl[wocl.Count - 1]);
wocl.Add(woc);
return woc;
}
else
{
return wocl[frameNumber];
}
}
}
}
Now when im doing loading the Load function i see the points its loading it good.
But then im trying to move the trackBar bar scroll to the right and then im getting the exception. Now thisl ine: wo1.woc.Point_X = test; the woc have 4 indexs and in each index Point_X and Point_Y are filled with numbers in each index.
In this class i have the functions SetFrame and GetFrame and im using GetFrame in Form1 scroll event of the trackBar:
private void trackBar1_Scroll(object sender, EventArgs e)
{
currentFrameIndex = trackBar1.Value;
textBox1.Text = "Frame Number : " + trackBar1.Value;
wireObject1.woc.Set(wireObjectAnimation1.GetFrame(currentFrameIndex));
LoadPictureAt(trackBar1.Value, sender);
button1.Enabled = false;
button2.Enabled = false;
button3.Enabled = false;
button4.Enabled = false;
button8.Enabled = false;
SaveFormPicutreBoxToBitMapIncludingDrawings();
return;
}
Now when im moving the trackBar once to the right it should paint the next set of numbers from the Point_X and Point_Y instead its going to the WireObjectCoordinates class and throw there the exception:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace AnimationEditor
{
class WireObjectCoordinates
{
public List<float> Point_X = new List<float>();
public List<float> Point_Y = new List<float>();
public WireObjectCoordinates()
{
}
public WireObjectCoordinates(WireObjectCoordinates w)
{
Point_X.AddRange(w.Point_X);
Point_Y.AddRange(w.Point_Y);
}
public void Set(WireObjectCoordinates w)
{
for (int i = 0; i < Point_X.Count; i++)
{
Point_X[i] = w.Point_X[i];
Point_Y[i] = w.Point_Y[i];
}
}
}
}
The exception is on the line: Point_X[i] = w.Point_X[i];
Point_X[i] contain now 4 indexs from [0] to [3] each index contain a number like 332.0 333.0 334.0 335.0
And w.Point_X[i] contain now only one index [0] and this index have the number 332.0
i just dont understand why the exception is on this line.
The idea is that when im moving the trackBar to the right it should draw the next coordinates from the wo1.woc.Point_Y and wo1.woc.Point_X but i guess i did something wrong in the Load function ? Im not sure why its throwing the exception and its only when im moving the trackBar to the right once.
How do you expect your for loop to work? The loop variable i goes from 0 to the count of the Point_X list of this instance. But if the other instance w has a Point_X list of a lower count, or if the Point_Y list of this or the Point_Y list of w has, it will fail.
If you realize that Point_X.Count is 4 and w.Point_X.Count is only 1, then when i exceeds 0, the expression w.Point_X[i] will try to read an element of the list that does not exist. That throws the excpetion "Index was out of range".
But maybe you understand that?
throw a try catch around it it technically wont fix the problem but it wont crash anymore and just read over the error