PDA

View Full Version : لود کردن مدل .obj



UfnCod3r
جمعه 06 بهمن 1391, 09:51 صبح
سلام
من میخوام مدل .obj لود کنم یعنی لود می کنم
اما .obj طوریه که برای بردار راس ها و نرمال ها و تکسچر همش یه ارایه اندیس جدا گرفته !:ناراحت:
یعنی این مدلیه !

class ObjModel
{
vector<Vec3> _Vertices;
vector<Vec3> _Normals;
vector<Vec2> _UVs;
vector<int> _Vertex_Indexes;
vector<int> _Normal_Indexes;
vector<int> _UV_Indexes;
}

من نمیخوام هر کدام یه ارایه اندیس جدا داشته باشه می خوام همش تو یکی با شه مثل همه مدل های تو بازی ها !
می خوام این طوری باشه ! چی کار باید کنم الگوریتمی چیزی داره !:ناراحت:

class StaticMesh
{
Vec3* _Vertices;
Vec3* _Normals;
Vec2* _UVs;
ushort _VertexCount;
ushort* _Indexes;
ushort _IndexCount;
GLuint _VBO1, _VBO2;
}

ببخشید اگه سوال رو خوب نپرسیدم !

amin.v
جمعه 06 بهمن 1391, 22:38 عصر
کار سختی نیست منتهی توضیح دادنش و نوشتن کدش طولانی هست !
فرمت ply ساختار ساده تری داره ، اندیس ها هم جدا نیستن

UfnCod3r
شنبه 07 بهمن 1391, 17:39 عصر
ply دیگه مال چیه !
اگه کدش داری بزار ! توضیح هم ندادی ندادی !:لبخند:
من از تو یه یه موتوری ادم ببینم توابع و .. زیاد بود نشد بفهمم !

amin.v
شنبه 07 بهمن 1391, 20:29 عصر
ply هم مثل obj یه فرمت ساده هست که اکثر نرم افزار ها خروجی میدن ( من با بلندر خروجی میگیرم )

اینجا توضیحات کلی داده در مورد این فرمت :
http://en.wikipedia.org/wiki/PLY_%28file_format%29

اما خلاصش اینکه این فرمت یه بخش header داره که اطلاعات مربوط به مش رو در خودش داره و از خطوط ply ( اولین خط ) شروع میشه و بعد هم با end_header تموم میشه ...
بعد از اون هم لیست ورتکسها و ایندکس هاست

من یه کد C# نوشتم منتهی ناقص هست و برا تست و این حرفها خودم استفاده میکنم ( یعنی مش باید position , normal , uv داشته باشه فقط و face ها هم triangulate شده باید باشن حتما ) اگه بدردت میخوره بگو بفرستم برات ...

UfnCod3r
شنبه 07 بهمن 1391, 21:58 عصر
اینو دیدم زیاد این فرمت ply جالب نیست یعنی افتضاهه ! :شکلک سبزه:
من باینری می خواستم ولی خب چه کنم اکسپورتر نوشتن خودش کاریه !
اون کده رو بده !
اون .obj رو هم کد تبدیلشو بده !
نمی دونم الان به این تبدیل اندیس ها و .. چی می گن وگگرنه سرچ می کردم !:ناراحت:
ببخشید وقتتو گرفتم !:خجالت:

amin.v
یک شنبه 08 بهمن 1391, 00:24 صبح
این فرمت نسخه باینری هم داره ، البته بلندر فقط ASCII خروجی میده ...
ضمنا اینکه افتضاحه رو من متوجه نشدم ! نمیشه گفت افتضاحه چون این فرمت یا هر فرمت عمومی دیگه یه ویژگی های خاص خودش رو داره ... کلا اگه هدفت ساخت یک بازی هست شما باید بری فرمت خودت رو بسازی بر اساس نیازهات نه اینکه مستقیم ply یا obj رو بخوای لود کنی ... اگر هم برا تست انجام میدی که هیچی !!
من هم خودم برا تست انجام میدم فعلا و قبلا گفتم ply رو به یه فرمت باینری خیلی ساده در میارم که از اونور لود کردنش هم راحت و نسبتا سریع هست ...
در مورد اندیس های obj هم کد ندارم ولی یه توضیح کوچیک میدم البته این یه روشه :
یه struct تعریف کن اینطوری :

struct vertexIndex
{
ushort index;
vec3 pos;
vec3 normal;
vec2 uv;
};

یه map هم درست کن بعد اندیس های obj رو ( یعنی مثلا 2/3/1 ) رو به عنوان key و یه struct هم به عنوان مقدار متناظر بهش میدی ... و این struct رو هم باید بر اساس همون اندیس obj مقادیرش رو پر کنی ...
بعد از اینکار هم یه map داری که تمام ورتکس ها توشه ... حالا لیست ورتکس ها رو درست میکنی و اندیس هایی که توش هست رو هم جایگزین میکنی با اون اندیس های obj.

این هم کد تبدیل ply ( باید opentk رو هم دانلود و رفرنس بدی )


using System;
using System.IO;
using System.Collections.Generic;

using OpenTK;

namespace ply2smf
{
class Program
{
public static string FirstWord(string str)
{
return str.Substring(0, Math.Max(0, str.IndexOf(' ')));
}
public static string LastWord(string str)
{
int i = str.LastIndexOf(' ') + 1;
return str.Substring(i ,str.Length - i);
}

struct meshData
{
public int vertexCount;
public int FaceCount;
public byte[] VerticesData;
public byte[] IndicesData;
}

static meshData ReadPly(string path)
{
StreamReader reader = File.OpenText(path);

if (reader.ReadLine() != "ply")
throw new Exception(path + " | is not ply file format.");

meshData mdata;
mdata.FaceCount = 0;
mdata.vertexCount = 0;

List<byte> vertices = new List<byte>();
List<byte> indices = new List<byte>();

string lastline;
do
{
lastline = reader.ReadLine();

if (FirstWord(lastline) == "element")
{
if (lastline.Contains("vertex"))
{
mdata.vertexCount = int.Parse(LastWord(lastline));
}
else if (lastline.Contains("face"))
{
mdata.FaceCount = int.Parse(LastWord(lastline));
}
}

}
while (lastline != "end_header");

for (int i = 0; i < mdata.vertexCount; i++)
{
lastline = reader.ReadLine();
string[] floats = lastline.Split(' ');
foreach (string s in floats)
{
vertices.AddRange(Half.GetBytes(Half.Parse(s)));
}
}

for (int i = 0; i < mdata.FaceCount; i++)
{
lastline = reader.ReadLine();
string[] ushorts = lastline.Split(' ');
for (int j = 1; j < ushorts.Length; j++)
{
indices.AddRange(BitConverter.GetBytes(ushort.Pars e(ushorts[j])));
}
}

mdata.VerticesData = vertices.ToArray();
mdata.IndicesData = indices.ToArray();

reader.Dispose();

return mdata;
}

static void SaveSmf(meshData data , string path)
{
FileStream stream = File.OpenWrite(path);
BinaryWriter writer = new BinaryWriter(stream);
writer.Write(data.vertexCount);
writer.Write(data.FaceCount);
writer.Write(data.VerticesData);
writer.Write(data.IndicesData);

writer.Dispose();
stream.Dispose();
}

static void Main(string[] args)
{
foreach (string path in args)
{
string filename = path.Substring(0, path.Length - 4);
SaveSmf(ReadPly(path), filename + ".smf");
}

}
}
}