commit x64 compilation from lulu cause the other branch dont seems to compile properly at home
This commit is contained in:
683
include/modules/import_obj/import_obj.cpp
Normal file
683
include/modules/import_obj/import_obj.cpp
Normal file
@ -0,0 +1,683 @@
|
||||
/* -----------------------------------------------------------------------------
|
||||
GSFramework
|
||||
Copyright 2001-2013 Emmanuel Julien. All Rights Reserved.
|
||||
----------------------------------------------------------------------------- */
|
||||
|
||||
|
||||
#include "import_obj/import_obj.h"
|
||||
#include "scene3d/scene.h"
|
||||
#include "scene3d/mobject.h"
|
||||
#include "core/graphic_resource_factory.h"
|
||||
#include "core/geometry.h"
|
||||
#include "metafile/nml_object.h"
|
||||
#include "ascii/parser.h"
|
||||
#include "filesystem/filesystem.h"
|
||||
#include "filesystem/io_handle.h"
|
||||
#include "platform.h"
|
||||
|
||||
using namespace GS;
|
||||
using namespace GS::Core;
|
||||
using namespace GS::S3D;
|
||||
using namespace GS::AsciiParser;
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
struct ObjPoly
|
||||
{
|
||||
List <int> vtx, uv, nrm;
|
||||
uint mat;
|
||||
|
||||
ObjPoly() : mat(0) {}
|
||||
};
|
||||
struct ObjGroup
|
||||
{
|
||||
String name;
|
||||
List <ObjPoly *> pol_list;
|
||||
|
||||
void Free()
|
||||
{ ListDeleteAllPtr(ObjPoly *, pol_list) }
|
||||
~ObjGroup()
|
||||
{ Free(); }
|
||||
};
|
||||
struct ObjMtl
|
||||
{
|
||||
String name;
|
||||
String path;
|
||||
};
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
static void ExportMaterialStage(NML::Tag *mtag, const String &texture, const char *channel, int index)
|
||||
{
|
||||
if (texture.IsEmpty())
|
||||
return;
|
||||
|
||||
if (NML::Tag *ttag = mtag->AddChild("TextureStage"))
|
||||
{
|
||||
ttag->AddChild("Active");
|
||||
ttag->AddChild("Texture", texture);
|
||||
ttag->AddChild("Channel", channel);
|
||||
ttag->AddChild("Index", index);
|
||||
}
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
bool OBJImporter::LoadMaterialLibrary(List <ObjMtl *> &mtl_list, const char *uri)
|
||||
{
|
||||
Array <char> obj;
|
||||
if (!Platform::Get().io->FileLoad(uri, obj))
|
||||
__ERR__(__LOG_E__ << "OBJ material library file '" << uri << "' not found.\n", false)
|
||||
|
||||
// Now parse.
|
||||
const char *pobj = &obj[0], *eobj = pobj + obj.GetSize();
|
||||
|
||||
ObjMtl *current_mtl = NULL;
|
||||
String map_Ka, map_Kd, map_Ks, map_Ke;
|
||||
|
||||
forever
|
||||
{
|
||||
String word(pobj, SkipEntry(pobj, eobj));
|
||||
|
||||
// Export material to file.
|
||||
if ((word == "newmtl") || (pobj >= eobj))
|
||||
if (current_mtl)
|
||||
{
|
||||
current_mtl->path = String::Format("%s/%s.nmm", config->base_path.c_str(), current_mtl->name.c_str());
|
||||
|
||||
// Only export material if it does not exist.
|
||||
if (!Platform::Get().io->Exists(current_mtl->path))
|
||||
{
|
||||
String name = Platform::Get().io->StripRootPath(current_mtl->path);
|
||||
|
||||
NML::File file;
|
||||
if (NML::Tag *mtag = file.AddRoot("Material"))
|
||||
{
|
||||
mtag->AddChild("Id", name);
|
||||
|
||||
ExportMaterialStage(mtag, map_Kd, "Diffuse", 0);
|
||||
ExportMaterialStage(mtag, map_Ka, "Opacity", 1);
|
||||
ExportMaterialStage(mtag, map_Ks, "Specular", 2);
|
||||
ExportMaterialStage(mtag, map_Ke, "Emissive", 3);
|
||||
|
||||
if (NML::Tag *rtag = mtag->AddChild("RenderMask"))
|
||||
rtag->AddChild("NormalMapTangent");
|
||||
}
|
||||
|
||||
NML::Parser::Save(current_mtl->path, file);
|
||||
}
|
||||
}
|
||||
|
||||
if (pobj >= eobj)
|
||||
break;
|
||||
|
||||
// Create new material.
|
||||
if (word == "newmtl")
|
||||
{
|
||||
// Create new material.
|
||||
mtl_list.Add(current_mtl = new ObjMtl);
|
||||
|
||||
pobj = NextEntry(pobj + 1, eobj);
|
||||
const char *eon = SkipEntry(pobj, eobj);
|
||||
|
||||
current_mtl->name.Set(pobj, eon);
|
||||
pobj = NextEntry(eon, eobj, true);
|
||||
}
|
||||
else if (current_mtl)
|
||||
{
|
||||
//------------------------------------------------------------------
|
||||
#define __ReadObjMaterialMap(_map) \
|
||||
{ \
|
||||
pobj = NextEntry(pobj + 1, eobj); \
|
||||
const char *eon = RunToEOL(pobj, eobj); \
|
||||
_map.Set(pobj, eon); \
|
||||
pobj = NextEntry(eon, eobj, true); \
|
||||
}
|
||||
//------------------------------------------------------------------
|
||||
|
||||
if (word == "map_Ka")
|
||||
__ReadObjMaterialMap(map_Ka)
|
||||
else if (word == "map_Ks")
|
||||
__ReadObjMaterialMap(map_Ks)
|
||||
else if (word == "map_Kd")
|
||||
__ReadObjMaterialMap(map_Kd)
|
||||
else if (word == "map_Ke")
|
||||
__ReadObjMaterialMap(map_Ke)
|
||||
else
|
||||
pobj = NextEntry(RunToEOL(pobj, eobj), eobj);
|
||||
}
|
||||
else
|
||||
pobj = NextEntry(RunToEOL(pobj, eobj), eobj);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
bool OBJImporter::TestImport(const char *uri)
|
||||
{
|
||||
String ext = String::FileGetExtension(uri).Lower();
|
||||
return ext == "obj";
|
||||
}
|
||||
bool OBJImporter::ImportScene(Scene *scene, const char *uri, const Config &_config, Group **)
|
||||
{
|
||||
Array <char> obj;
|
||||
if (!Platform::Get().io->FileLoad(uri, obj))
|
||||
__ERR__(__LOG_E__ << "OBJ file '" << uri << "' not found.\n", false)
|
||||
|
||||
// Now parse.
|
||||
config = &_config;
|
||||
if (config->event_handler)
|
||||
config->event_handler->OpenLoad();
|
||||
|
||||
const char *pobj = &obj[0], *eobj = pobj + obj.GetSize();
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
{
|
||||
bool has_uv = false, has_vnm = false;
|
||||
AutoList <Vector4 *> vtx_list, vnm_list;
|
||||
AutoList <Vector2 *> uv_list;
|
||||
|
||||
AutoList <ObjGroup *> group_list;
|
||||
AutoList <ObjMtl *> mat_list;
|
||||
|
||||
ObjGroup *current_group = new ObjGroup;
|
||||
current_group->name = "default";
|
||||
group_list.Add(current_group);
|
||||
|
||||
int current_mat = 0;
|
||||
|
||||
while (pobj < eobj)
|
||||
{
|
||||
String word(pobj, SkipEntry(pobj, eobj));
|
||||
|
||||
if (config->event_handler)
|
||||
config->event_handler->LoadProgress(String::Format("Parsing tag '%s'...", word.c_str()), (float)(pobj - &obj[0]) / obj.GetSize());
|
||||
|
||||
// Declare material library.
|
||||
if (word == "mtllib")
|
||||
{
|
||||
pobj = NextEntry(pobj + 1, eobj);
|
||||
const char *eon = RunToEOL(pobj, eobj);
|
||||
|
||||
String lib_path = String(pobj, eon);
|
||||
if (!lib_path.IsAbsolutePath())
|
||||
lib_path = String(uri).GetFilePath() + "/" + lib_path;
|
||||
|
||||
LoadMaterialLibrary(mat_list, lib_path);
|
||||
pobj = NextEntry(eon, eobj, true);
|
||||
}
|
||||
|
||||
// Use material.
|
||||
else if (word == "usemtl")
|
||||
{
|
||||
pobj = NextEntry(pobj + 1, eobj);
|
||||
const char *eon = SkipEntry(pobj, eobj);
|
||||
String name(pobj, eon);
|
||||
|
||||
// Locate in library.
|
||||
current_mat = 0;
|
||||
ListForeachPtr(ObjMtl *, mat, mat_list)
|
||||
{
|
||||
if (mat->name == name)
|
||||
break;
|
||||
current_mat++;
|
||||
}
|
||||
|
||||
pobj = NextEntry(eon, eobj, true);
|
||||
}
|
||||
|
||||
// Append vertex.
|
||||
else if (word == "v")
|
||||
{
|
||||
// Parse vertex.
|
||||
pobj = NextEntry(pobj, eobj);
|
||||
|
||||
float x = 0, y = 0, z = 0;
|
||||
|
||||
x = String::atof(pobj, eobj); pobj = NextEntry(pobj, eobj, true);
|
||||
y = String::atof(pobj, eobj); pobj = NextEntry(pobj, eobj, true);
|
||||
z = String::atof(pobj, eobj); pobj = NextEntry(pobj, eobj, true);
|
||||
|
||||
vtx_list.Add(new Vector4(x * config->scale, y * config->scale, -z * config->scale));
|
||||
}
|
||||
|
||||
// Append vertex normal.
|
||||
else if (word == "vn")
|
||||
{
|
||||
pobj = NextEntry(pobj, eobj);
|
||||
|
||||
float x = 0, y = 0, z = 0;
|
||||
|
||||
x = String::atof(pobj, eobj); pobj = NextEntry(pobj, eobj, true);
|
||||
y = String::atof(pobj, eobj); pobj = NextEntry(pobj, eobj, true);
|
||||
z = String::atof(pobj, eobj); pobj = NextEntry(pobj, eobj, true);
|
||||
|
||||
// vnm_list.Add(new nVector(-y, -z, -x));
|
||||
vnm_list.Add(new Vector4(x, y, -z));
|
||||
}
|
||||
|
||||
// Append UV.
|
||||
else if (word == "vt")
|
||||
{
|
||||
pobj = NextEntry(pobj, eobj);
|
||||
|
||||
float u = 0, v = 0;
|
||||
|
||||
u = String::atof(pobj, eobj); pobj = NextEntry(pobj, eobj, true);
|
||||
v = String::atof(pobj, eobj); pobj = NextEntry(pobj, eobj, true);
|
||||
|
||||
uv_list.Add(new Vector2(u, 1.f - v));
|
||||
}
|
||||
|
||||
// Declare group.
|
||||
else if (word == "g")
|
||||
{
|
||||
group_list.Add(current_group = new ObjGroup);
|
||||
|
||||
// Check for named group.
|
||||
const char *eol = RunToEOL(pobj, eobj);
|
||||
pobj = NextEntry(pobj + 1, eobj);
|
||||
|
||||
if (pobj <= eol)
|
||||
{
|
||||
const char *eon = SkipEntry(pobj, eobj);
|
||||
current_group->name.Set(pobj, eon);
|
||||
pobj = NextEntry(eon, eobj, true);
|
||||
}
|
||||
else // no name
|
||||
pobj = NextEntry(eol, eobj, true);
|
||||
}
|
||||
|
||||
// Build group polygons.
|
||||
else if (word == "f")
|
||||
{
|
||||
pobj = NextEntry(pobj, eobj);
|
||||
|
||||
ObjPoly *pol = new ObjPoly;
|
||||
pol->mat = current_mat;
|
||||
|
||||
const char *eol = RunToEOL(pobj, eobj);
|
||||
while (pobj < eol)
|
||||
{
|
||||
pol->vtx.Add(String::atoi(pobj)); // Index.
|
||||
pobj = NextEntry(pobj, eobj, true);
|
||||
|
||||
if (pobj[0] == '/')
|
||||
{
|
||||
pobj++;
|
||||
if (pobj[0] != '/')
|
||||
{
|
||||
has_uv = true;
|
||||
pol->uv.Add(String::atoi(pobj)); // UV index.
|
||||
pobj = NextEntry(pobj, eobj, true);
|
||||
}
|
||||
}
|
||||
|
||||
if (pobj[0] == '/')
|
||||
{
|
||||
pobj++;
|
||||
has_vnm = true;
|
||||
pol->nrm.Add(String::atoi(pobj)); // Normal index.
|
||||
pobj = NextEntry(pobj, eobj, true);
|
||||
}
|
||||
}
|
||||
|
||||
if (pol->vtx.GetCount() < 3)
|
||||
delete pol;
|
||||
else
|
||||
current_group->pol_list.Add(pol);
|
||||
}
|
||||
else
|
||||
pobj = NextEntry(RunToEOL(pobj, eobj), eobj);
|
||||
}
|
||||
|
||||
obj.Free();
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
|
||||
// Get flat UV array.
|
||||
Array <Vector2> flat_uv;
|
||||
if (has_uv && flat_uv.Allocate(uv_list.GetCount()))
|
||||
{
|
||||
Vector2 *pflat_uv = flat_uv;
|
||||
ListForeachPtr(Vector2 *, uv, uv_list)
|
||||
*pflat_uv++ = *uv;
|
||||
}
|
||||
|
||||
// Get flat vertex normal array.
|
||||
Array <Vector4> flat_vnm;
|
||||
if (has_vnm && flat_vnm.Allocate(vnm_list.GetCount()))
|
||||
{
|
||||
Vector4 *pflat_vnm = flat_vnm;
|
||||
ListForeachPtr(Vector4 *, vnm, vnm_list)
|
||||
*pflat_vnm++ = *vnm;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
|
||||
Array <int> vtx_map(vtx_list.GetCount()),
|
||||
mat_map(mat_list.GetCount());
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
|
||||
// Build scene.
|
||||
int n_pg = 0;
|
||||
ListForeachPtr(ObjGroup *, group, group_list)
|
||||
{
|
||||
++n_pg;
|
||||
if (!vtx_list.GetCount() || !group->pol_list.GetCount())
|
||||
continue;
|
||||
|
||||
if (config->event_handler)
|
||||
config->event_handler->LoadProgress(String::Format("Importing group '%s'...", group->name.toUtf8()), (float)(n_pg - 1) / group_list.GetCount());
|
||||
|
||||
// Create geometry.
|
||||
Geometry *geo = new Geometry;
|
||||
|
||||
// Remap vertices.
|
||||
for (uint n = 0; n < vtx_map.GetCount(); ++n)
|
||||
vtx_map[n] = -1;
|
||||
|
||||
// Total vertex count.
|
||||
uint vtx_count = 0;
|
||||
ListForeachPtr(ObjPoly *, p, group->pol_list)
|
||||
ListForeachPtr(int, i, p->vtx)
|
||||
if (vtx_map[i - 1] == -1)
|
||||
vtx_map[i - 1] = vtx_count++;
|
||||
|
||||
// Transfer vertices.
|
||||
if (geo->vtx.Allocate(vtx_count))
|
||||
{
|
||||
for (uint i = 0; i < vtx_list.GetCount(); ++i)
|
||||
if (vtx_map[i] != -1)
|
||||
geo->vtx[vtx_map[i]] = *vtx_list[i];
|
||||
}
|
||||
else
|
||||
__LOG_E__ << "Failed to allocate " << geo->vtx.GetCount() << " vertices.\n";
|
||||
|
||||
// Transfer topology and attributes.
|
||||
if (geo->pol.Allocate(group->pol_list.GetCount()))
|
||||
{
|
||||
// Compute bind index count.
|
||||
uint binding_count = 0;
|
||||
ListForeachPtr(ObjPoly *, p, group->pol_list)
|
||||
binding_count += p->vtx.GetCount();
|
||||
|
||||
if (geo->binding.Allocate(binding_count))
|
||||
{
|
||||
uint *pbind = &geo->binding[0];
|
||||
|
||||
// Allocate attributes.
|
||||
Vector2 *puv = NULL;
|
||||
if (has_uv)
|
||||
{
|
||||
geo->uv[0].Allocate(binding_count);
|
||||
puv = &geo->uv[0][0];
|
||||
}
|
||||
|
||||
Vector4 *pvnm = NULL;
|
||||
if (has_vnm)
|
||||
{
|
||||
geo->vtx_normal.Allocate(binding_count);
|
||||
pvnm = &geo->vtx_normal[0];
|
||||
}
|
||||
|
||||
// Transfer data.
|
||||
uint cpol = 0;
|
||||
ListForeachPtr(ObjPoly *, p, group->pol_list)
|
||||
{
|
||||
Polygon *pol = &geo->pol[cpol++];
|
||||
|
||||
pol->vtx_count = (ushort)p->vtx.GetCount();
|
||||
pol->binding = pbind;
|
||||
pol->material = 0;
|
||||
|
||||
for (int i = p->vtx.GetCount(); i > 0; --i)
|
||||
{
|
||||
int idx = p->vtx[i - 1] - 1;
|
||||
if (idx > (int)vtx_map.GetCount())
|
||||
idx = 0;
|
||||
*pbind++ = vtx_map[idx];
|
||||
}
|
||||
|
||||
if (puv)
|
||||
for (int i = p->uv.GetCount(); i > 0; --i)
|
||||
*puv++ = flat_uv[p->uv[i - 1] - 1];
|
||||
|
||||
if (pvnm)
|
||||
for (int i = p->nrm.GetCount(); i > 0; --i)
|
||||
*pvnm++ = flat_vnm[p->nrm[i - 1] - 1];
|
||||
}
|
||||
}
|
||||
else
|
||||
__LOG_E__ << "Failed to allocate " << geo->binding.GetCount() << " polygon binding entries.\n";
|
||||
|
||||
// Remap and assign materials.
|
||||
for (uint i = 0; i < mat_list.GetCount(); ++i)
|
||||
mat_map[i] = -1;
|
||||
|
||||
int mat_count = 0;
|
||||
ListForeachPtr(ObjPoly *, p, group->pol_list)
|
||||
if (p->mat < mat_map.GetCount())
|
||||
if (mat_map[p->mat] == -1)
|
||||
mat_map[p->mat] = mat_count++;
|
||||
|
||||
uint cpol = 0;
|
||||
ListForeachPtr(ObjPoly *, p, group->pol_list)
|
||||
geo->pol[cpol++].material = (ushort)(p->mat < mat_map.GetCount() ? mat_map[p->mat] : 0);
|
||||
|
||||
// Load materials.
|
||||
if (mat_list.GetCount())
|
||||
{
|
||||
geo->material_table.Allocate(mat_count);
|
||||
for (uint i = 0; i < mat_list.GetCount(); ++i)
|
||||
if (mat_map[i] != -1)
|
||||
geo->material_table[mat_map[i]].name = mat_list[i]->path;
|
||||
}
|
||||
else
|
||||
geo->material_table.Allocate(1);
|
||||
|
||||
// Vertex normal.
|
||||
if (!has_vnm)
|
||||
geo->ComputeVertexNormal(true);
|
||||
|
||||
// Save geometry.
|
||||
geo->name = String::Format("%s/%s.nmg", config->base_path.c_str(), group->name.toUtf8());
|
||||
NML::SaveToFile(*geo, geo->name);
|
||||
|
||||
geo->name = Platform::Get().io->StripRootPath(geo->name);
|
||||
|
||||
// Add to scene.
|
||||
MObject *object = new MObject;
|
||||
object->name = group->name;
|
||||
scene->AddItem(object, true);
|
||||
object->geometry = geo->name;
|
||||
|
||||
// Ease up memory.
|
||||
group->Free();
|
||||
}
|
||||
else
|
||||
__LOG_E__ << "Failed to allocate " << geo->pol.GetCount() << " polygons.\n";
|
||||
}
|
||||
}
|
||||
//--------------------------------------------------------------------------
|
||||
|
||||
// Save scene.
|
||||
scene->name = String::Format("%s/scene.nms", config->base_path.c_str());
|
||||
NML::SaveToFile(*scene, scene->name);
|
||||
scene->name = Platform::Get().io->StripRootPath(scene->name);
|
||||
|
||||
if (config->event_handler)
|
||||
config->event_handler->EndLoad();
|
||||
return true;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
Geometry *OBJImporter::ImportGeometry(const char *uri, IResourceFactoryEvent *event_handler)
|
||||
{
|
||||
if (!uri)
|
||||
__ERR__(__LOG_E__ << "No URI to import.\n", NULL)
|
||||
|
||||
AutoPtr <Geometry> geo(new Geometry);
|
||||
|
||||
// Load file in memory.
|
||||
Array <char> obj;
|
||||
if (!Platform::Get().io->FileLoad(uri, obj))
|
||||
__ERR__(__LOG_E__ << "File '" << uri << "' not found.\n", NULL)
|
||||
|
||||
// Now parse.
|
||||
List <Vector4 *> vtx_list;
|
||||
List <Vector2 *> uv_list;
|
||||
List <ObjPoly *> pol_list;
|
||||
|
||||
bool has_uv = false;
|
||||
const char *pobj = &obj[0], *eobj = pobj + obj.GetSize();
|
||||
|
||||
while (pobj < eobj)
|
||||
{
|
||||
String word(pobj, SkipEntry(pobj, eobj));
|
||||
|
||||
if (word == "v")
|
||||
{
|
||||
pobj = NextEntry(pobj, eobj);
|
||||
|
||||
float x = 0, y = 0, z = 0;
|
||||
|
||||
x = String::atof(pobj, eobj);
|
||||
pobj = NextEntry(pobj, eobj, true);
|
||||
y = String::atof(pobj, eobj);
|
||||
pobj = NextEntry(pobj, eobj, true);
|
||||
z = -String::atof(pobj, eobj);
|
||||
pobj = NextEntry(pobj, eobj, true);
|
||||
|
||||
vtx_list.Add(new Vector4(x, y, z));
|
||||
}
|
||||
else if (word == "vt")
|
||||
{
|
||||
pobj = NextEntry(pobj, eobj);
|
||||
|
||||
float u = 0, v = 0;
|
||||
|
||||
u = String::atof(pobj, eobj);
|
||||
pobj = NextEntry(pobj, eobj, true);
|
||||
v = String::atof(pobj, eobj);
|
||||
pobj = NextEntry(pobj, eobj, true);
|
||||
|
||||
uv_list.Add(new Vector2(u, v));
|
||||
}
|
||||
else if (word == "f")
|
||||
{
|
||||
pobj = NextEntry(pobj, eobj);
|
||||
|
||||
ObjPoly *pol = new ObjPoly;
|
||||
pol_list.Add(pol);
|
||||
|
||||
const char *eol = RunToEOL(pobj, eobj);
|
||||
while (pobj < eol)
|
||||
{
|
||||
pol->vtx.Add(String::atoi(pobj)); // Index.
|
||||
pobj = NextEntry(pobj, eobj, true);
|
||||
|
||||
if (pobj[0] == '/')
|
||||
{
|
||||
pobj++;
|
||||
if (pobj[0] != '/')
|
||||
{
|
||||
has_uv = true;
|
||||
pol->uv.Add(String::atoi(pobj)); // UV index.
|
||||
pobj = NextEntry(pobj, eobj, true);
|
||||
}
|
||||
}
|
||||
|
||||
if (pobj[0] == '/')
|
||||
{
|
||||
pobj++;
|
||||
pol->nrm.Add(String::atoi(pobj)); // Normal index.
|
||||
pobj = NextEntry(pobj, eobj, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
pobj = NextEntry(RunToEOL(pobj, eobj), eobj);
|
||||
}
|
||||
|
||||
// Drop OBJ.
|
||||
obj.Free();
|
||||
|
||||
// Transfer vertice.
|
||||
if (geo->vtx.Allocate(vtx_list.GetCount()))
|
||||
{
|
||||
uint cvtx = 0;
|
||||
ListForeachPtr(Vector4 *, v, vtx_list)
|
||||
geo->vtx[cvtx++] = *v;
|
||||
}
|
||||
else
|
||||
__LOG_E__ << "Failed to allocate " << vtx_list.GetCount() << " vertices.\n";
|
||||
|
||||
ListDeleteAllPtr(Vector4 *, vtx_list)
|
||||
|
||||
// Transfer polygon.
|
||||
if (geo->pol.Allocate(pol_list.GetCount()))
|
||||
{
|
||||
uint binding_count = 0;
|
||||
ListForeachPtr(ObjPoly *, p, pol_list)
|
||||
binding_count += p->vtx.GetCount();
|
||||
|
||||
geo->binding.Allocate(binding_count);
|
||||
|
||||
Array <Vector2> flat_uv;
|
||||
|
||||
if (has_uv)
|
||||
if (flat_uv.Allocate(binding_count))
|
||||
{
|
||||
geo->uv[0].Allocate(binding_count);
|
||||
|
||||
Vector2 *pflat_uv = &flat_uv[0];
|
||||
ListForeachPtr(Vector2 *, uv, uv_list)
|
||||
*pflat_uv++ = *uv;
|
||||
|
||||
ListDeleteAllPtr(Vector2 *, uv_list)
|
||||
}
|
||||
|
||||
Vector2 *puv = &geo->uv[0][0];
|
||||
|
||||
if (geo->binding)
|
||||
{
|
||||
uint *pbind = &geo->binding[0];
|
||||
|
||||
uint cpol = 0;
|
||||
ListForeachPtr(ObjPoly *, p, pol_list)
|
||||
{
|
||||
Polygon *pol = &geo->pol[cpol];
|
||||
|
||||
pol->vtx_count = (ushort)p->vtx.GetCount();
|
||||
pol->binding = pbind;
|
||||
pol->material = 0;
|
||||
|
||||
for (int v = p->vtx.GetCount(); v > 0; --v)
|
||||
*pbind++ = p->vtx.ObjectAt(v - 1) - 1;
|
||||
|
||||
ListForeachPtr(int, i, p->uv)
|
||||
*puv++ = flat_uv[i - 1];
|
||||
}
|
||||
}
|
||||
else
|
||||
__LOG_E__ << "Failed to allocate " << geo->binding.GetCount() << " polygon binding entries.\n";
|
||||
}
|
||||
else
|
||||
__LOG_E__ << "Failed to allocate " << geo->pol.GetCount() << " polygons.\n";
|
||||
|
||||
ListDeleteAllPtr(ObjPoly *, pol_list)
|
||||
|
||||
// Load materials.
|
||||
geo->material_table.Allocate(1);
|
||||
geo->material_table[0].name = "Default";
|
||||
|
||||
// Setup defaults.
|
||||
geo->ComputeVertexNormal();
|
||||
|
||||
return geo.Detach();
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
Reference in New Issue
Block a user