Start a new topic

I can't seem to save out a DB with a mesh

Original Post by: MarcFlores Mon Aug 26 22:38:10 2013


I don't think I'm doing anything wrong when building the DB with my mesh, since it looks the way I want when I walk through the DB. So I'm not going to include that code initially. However, after I close the DB, and then reopen the file, nothing is in there. Is there some sort of commit, or some other step I'm missing?


I should add that the file size of the DB doesn't seem to change after the first mgCloseDb() call. It's almost like the mesh data is in the DB memory, but is never written out to the file. Otherwise I would expect the file that does not have the mesh to be smaller in size.


// write the database

if (MG_FALSE == mgWriteDb(db)) {

//***I don't get in here, so the write call seems to be working***

status = STD_FILE_WRITE_FAILED;

}


// Test if the output DB has the data in it

//***DURING THIS WALK THE DB HAS THE DATA I WANT***

mgWalk(db, walkMesh, MG_NULL, MG_NULL, MWALK_NOREADONLY);

mgCloseDb(db);


// Test if the output DB still has the data in it after closing

mgrec* debug_db;

debug_db = mgOpenDb(db_path.c_str());

//***DURING THIS WALK THE DB NO LONGER HAS THE DATA I WANT***

mgWalk(debug_db, walkMesh, MG_NULL, MG_NULL, MWALK_NOREADONLY);

mgCloseDb(debug_db);


Original Post by: SteveThompson Tue Aug 27 13:17:20 2013


Could it be you are writing to OpenFlight 15.6 or older? If so, mesh nodes were not introduced until OpenFlight 15.7. When writing to earlier OpenFlight specifications the OpenFlight API "strips" out mesh nodes on write.


Are these the same mgWalk flags you are really using? You may not "see" the mesh nodes in your mgWalk if you really are specifying WALK_ON and the meshes are part of an LOD that is not initially "ON" after you open.


Otherwise, I can't think of a reason you don't see the mesh nodes.


Let us know which version of OpenFlight you are "writing" and which version of the OpenFlight API you are using.


Thanks

Original Post by: MarcFlores Tue Aug 27 15:19:42 2013


I am using API version 4.2. Those are in fact the mgWalk flags I am using.


I don't specify a DB version (but I would like to), nor do I see any way in the API to do so. Does it just use the latest version if not specified? I just use this call:

mgrec* db = mgNewDb(db_path.c_str());


I don't think this is important, but I should mention that I am working in a Class, not a basic console application. So I do initiatialization like this (is this a problem?):

int num_args = 0;

mgInit(#_args, NULL);

Original Post by: SteveThompson Tue Aug 27 15:40:55 2013


I don’t specify a DB version (but I would like to), nor do I see any way in the API to do so.
You use mgExportDb to write out "older" versions of OpenFlight.


I don’t think this is important, but I should mention that I am working in a Class, not a basic console application. So I do initiatialization like this (is this a problem?):

Depends on how you do this, just be aware that you cannot call mgInit more than one time in your process. i.e. you CANNOT do this in your program:


mgInit

// do some stuff

mgExit


// wait a bit


mgInit

// do some more stuff

mgExit


Original Post by: MarcFlores Tue Aug 27 15:50:50 2013


Oh, well that could be a problem in the future. I call mgInit() in my class constructor, and mgExit() when I'm done with the object. Then I would expect to be able to create another instance of my class to use, but that would call mgInit() again. If I can't do that, then I guess I'll have to make my class a Singleton.


This doesn't explain my current problem though, since I only call mgInit() once in my current testing. I must be missing something with mgExportDb(). I saw that, but that would create a "new" file. I don't want to create the original file using mgOpenDb, then turn around and create a second, versioned copy using mgExportDb. Or can I simply give the original path, and mgExportDb will just overwrite the original?

Original Post by: SteveThompson Tue Aug 27 16:04:35 2013


I must be missing something with mgExportDb(). I saw that, but that would create a “new” file. I don’t want to create the original file using mgOpenDb, then turn around and create a second, versioned copy using mgExportDb. Or can I simply give the original path, and mgExportDb will just overwrite the original?

Yes, just export to the same file name, no problem.


As for you original problem (and sorry to have to ask)... you are calling mgWriteDb before mgExit right?

Original Post by: MarcFlores Tue Aug 27 16:23:14 2013


No, it's a fair question, but I did not fall into that trap. I do call mgWrite before mgExit. I call mgWrite multiple times in fact before mgExit. I can call mgWrite as many times as I want, right?


One other question, and then I'll leave you alone for a while. I can call mgAttach over and over to iterate through the Meshes and add to the DB right, or should I be using mgAppend? Here are some code snippets from what I'm using to init the DB and add meshes:


mgSetNewOverwriteFlag(MG_TRUE);

mgrec* db = mgNewDb(db_path.c_str());

mgrec* db_group = MG_NULL;

mgrec* db_object = MG_NULL;


db_group = mgNewRec(fltGroup);

if (MG_NULL != db_group) {

db_object = mgNewRec(fltObject);

if (MG_NULL != db_object) {

mgAttach(db, db_group);

mgAttach(db_group, db_object);

}

}


mgrec* db_mesh = mgNewRec(fltMesh);

// use mgMesh* calls to create the Mesh...


// These get called over and over for each mesh

mgAttach(db_object, db_mesh);

mgWriteDb(db);


// After ALL meshes attached, and written

mgExit();

Original Post by: SteveThompson Tue Aug 27 16:36:11 2013


No bother... we want to help you solve your problem whatever it takes ;-)


I can call mgWrite as many times as I want, right?

Yes, no problem.


I can call mgAttach over and over to iterate through the Meshes and add to the DB right, or should I be using mgAppend?

Up to you... mgAttach puts new node as "first" child of parent, mgAppend puts new node as "last" child of parent. Makes no difference to the API so use them the way you want to build your hierarchy. Do note that mgAppend is a bit more expensive since it has to "look" for the last child while mgAttach simply puts on front of linked list and fixes some pointers. That said, you can play tricks by mgAttaching in "reverse" order to get what you really want in the hierarchy.

Original Post by: MarcFlores Tue Aug 27 16:43:21 2013


You lost me a bit with mgNewDb. When I call that I am providing a "real" file path (db_path is a variable that contains a string that is a valid file path). That file is in fact being created, so I know that mgNewDb is creating a real file at that location. Then I use mgWrite to write to the DB at the file location.


Are you saying I should not provide a full file path to mgNewDb, but instead just a name, and then use mgSaveAsDb with a file path to actually write to a file location?

Original Post by: SteveThompson Tue Aug 27 17:08:49 2013


Oops, disregard my last message about mgNewDb. I was thinking about the internal functions, not the external functions. The "internal" "new db" function makes an untitled "temp" file, the external (mgNewDb) function takes a file name and uses that. You are right. Forgive me... I updated my last post so as to erase any proof of my temporary ignorance ;-)


Your snippet is spot on... my bad.

Original Post by: MarcFlores Tue Aug 27 23:12:59 2013


If you attach an object, and then manipulate the object, is the attached object changed, or do I need to be done with an object before I attach it?


I create the basic DB structure up front like so:

.

mgrec* db_group1 = MG_NULL;

mgrec* db_group2 = MG_NULL;

mgrec* db_object = MG_NULL;


db_group1 = mgNewRec(fltGroup);

db_group2 = mgNewRec(fltGroup);

if (MG_NULL != db_group1 && MG_NULL != db_group2)

{

db_object = mgNewRec(fltObject);

if (MG_NULL != db_object)

{

mgAttach(db, db_group1);

mgAttach(db_group1, db_group2);

mgAttach(db_group2, db_object);

}

}


Then I create the mesh node and build it up. Then I attach the mesh node to the fltOject that I created before. To me, that now means that it is part of the DB hierarchy.


Am I supposed to work in reverse for some reason? That is, am I required to build up the mesh, then create the fltObject, and attach the mesh. Then create the fltGroup and attach the fltObject, and then work my way all the way up to the DB, or can I attach everything up front, and edit later?

Original Post by: SteveThompson Tue Aug 27 23:21:24 2013


You can make changes to an object (or any node) regardless of whether it is attached or not. The mgAttach is simply connecting pointers (no finalization stuff like you suggest). So you can set all the attributes of the object then attach then set some more attributes. Or you can attach then set all the attributes. It does not matter.


Just be aware that if you never attach it, it won't be saved in the OpenFlight file. mgNewRec by itself just creates a new (orphan) node. To really make it go, you have to put it into the hierarchy (or it will simply get lost when you close the db).


Hope that makes sense.

Original Post by: MarcFlores Tue Sep 3 23:42:59 2013


Okay, I still can't get this to work. My code to build meshes is pretty complex, so I decided to go back to square one. Now I'm creating a very simple cube shaped mesh (no normals, no textures, just vertices!), and it still doesn't work. I stepped through each line, and none of my "mg" calls returns any kind of error, or bad return value. I get a FLT file written out, but it doesn't contain my mesh.


Can anybody spot something I'm doing wrong below?

bool OfWriter::writeTestMesh(mgrec* db, mgrec* db_object)

{

bool written = false;


mgrec* db_mesh = mgNewRec(fltMesh);

if (MG_NULL != db_mesh)

{

int num_verts = 8;

int num_db_prims = 12;

if ( MG_FALSE != mgMeshCreatePrimitives(db_mesh, num_db_prims) )

{

if ( NULL !=

mgMeshCreateVtxPool(db_mesh,

MMESH_VTXCOORD | MMESH_VTXCOLORRGB | MMESH_VTXNORMAL | MMESH_VTXUV0,

num_verts) )

{

// create vector of vertices

std::vector<std::vector<double>> vertices;

static const double apt0[] = {-117.198, 32.7573, 0.595680654980242252349853515625};

std::vector<double> pt0(apt0, apt0 + sizeof(apt0) / sizeof(apt0[0]) );

vertices.push_back(pt0);

static const double apt1[] = {-117.198, 32.7801, 0.595680654980242252349853515625};

std::vector<double> pt1(apt1, apt1 + sizeof(apt1) / sizeof(apt1[0]) );

vertices.push_back(pt1);

static const double apt2[] = {-117.174, 32.7801, 0.595680654980242252349853515625};

std::vector<double> pt2(apt2, apt2 + sizeof(apt2) / sizeof(apt2[0]) );

vertices.push_back(pt2);

static const double apt3[] = {-117.174, 32.7573, 0.595680654980242252349853515625};

std::vector<double> pt3(apt3, apt3 + sizeof(apt3) / sizeof(apt3[0]) );

vertices.push_back(pt3);

static const double apt4[] = {-117.174, 32.7801, 19.879814148880541324615478515625};

std::vector<double> pt4(apt4, apt4 + sizeof(apt4) / sizeof(apt4[0]) );

vertices.push_back(pt4);

static const double apt5[] = {-117.174, 32.7573, 19.879814148880541324615478515625};

std::vector<double> pt5(apt5, apt5 + sizeof(apt5) / sizeof(apt5[0]) );

vertices.push_back(pt5);

static const double apt6[] = {-117.198, 32.7801, 19.879814148880541324615478515625};

std::vector<double> pt6(apt6, apt6 + sizeof(apt6) / sizeof(apt6[0]) );

vertices.push_back(pt6);

static const double apt7[] = {-117.198, 32.7573, 19.879814148880541324615478515625};

std::vector<double> pt7(apt7, apt7 + sizeof(apt7) / sizeof(apt7[0]) );

vertices.push_back(pt7);


// add point coords to vertex vector

std::vector<std::vector<double>>::const_iterator v_iter = vertices.begin();

int pt = 0;

for (; v_iter != vertices.end(); ++v_iter)

{

double pt_x = (*v_iter)[0];

double pt_y = (*v_iter)[1];

double pt_z = (*v_iter)[2];

if ( MG_FALSE !=

mgMeshSetVtxCoord(db_mesh, pt, pt_x, pt_y, pt_z) )

{

mgMeshSetVtxColorRGB(db_mesh, pt, 189, 27, 27);

}


pt++;

}


// Create vector of the primitive triangles and

// assign the vertex indices to each primitive triangle.

std::vector<std::vector<int>> primitives;

static const int prm0[] = {0,1,3};

std::vector<int> vprm0(prm0, prm0 + sizeof(prm0) / sizeof(prm0[0]) );

primitives.push_back(vprm0);

static const int prm1[] = {1,2,3};

std::vector<int> vprm1(prm1, prm1 + sizeof(prm1) / sizeof(prm1[0]) );

primitives.push_back(vprm1);

static const int prm2[] = {3,2,5};

std::vector<int> vprm2(prm2, prm2 + sizeof(prm2) / sizeof(prm2[0]) );

primitives.push_back(vprm2);

static const int prm3[] = {2,4,5};

std::vector<int> vprm3(prm3, prm3 + sizeof(prm3) / sizeof(prm3[0]) );

primitives.push_back(vprm3);

static const int prm4[] = {5,4,7};

std::vector<int> vprm4(prm4, prm4 + sizeof(prm4) / sizeof(prm4[0]) );

primitives.push_back(vprm4);

static const int prm5[] = {4,6,7};

std::vector<int> vprm5(prm5, prm5 + sizeof(prm5) / sizeof(prm5[0]) );

primitives.push_back(vprm5);

static const int prm6[] = {7,6,0};

std::vector<int> vprm6(prm6, prm6 + sizeof(prm6) / sizeof(prm6[0]) );

primitives.push_back(vprm6);

static const int prm7[] = {6,1,0};

std::vector<int> vprm7(prm7, prm7 + sizeof(prm7) / sizeof(prm7[0]) );

primitives.push_back(vprm7);

static const int prm8[] = {7,0,5};

std::vector<int> vprm8(prm8, prm8 + sizeof(prm8) / sizeof(prm8[0]) );

primitives.push_back(vprm8);

static const int prm9[] = {0,3,5};

std::vector<int> vprm9(prm9, prm9 + sizeof(prm9) / sizeof(prm9[0]) );

primitives.push_back(vprm9);

static const int prm10[] = {1,6,2};

std::vector<int> vprm10(prm10, prm10 + sizeof(prm10) / sizeof(prm10[0]) );

primitives.push_back(vprm10);

static const int prm11[] = {6,4,2};

std::vector<int> vprm11(prm11, prm11 + sizeof(prm11) / sizeof(prm11[0]) );

primitives.push_back(vprm11);


std::vector<std::vector<int>>::const_iterator p_iter = primitives.begin();

int db_prim_index = 0;

for (; p_iter != primitives.end(); ++p_iter)

{

if ( MG_FALSE ==

mgMeshPrimitiveSetType(db_mesh, db_prim_index,

MPRIM_INDEXED_POLY) )

{

break; // all primitives must be valid

}


if ( 0 <

mgMeshPrimitiveSetVtxIndexArray(db_mesh, db_prim_index,

const_cast<int*>(&((*p_iter)[0])), (*p_iter).size()) )

{

db_prim_index++;

}

else

{

break;

}

}


if (num_db_prims == db_prim_index)

{

if (MG_FALSE != mgAttach(db_object, db_mesh))

{

if (MG_FALSE != mgWriteDb(db))

{

written = true;

}

}

}

}

}

}


return written;

}

Original Post by: SteveThompson Wed Sep 4 16:40:50 2013


I just put your code into one of the sample apps and it seems to work fine. It creates one mesh node, prints out during mgWalk following write and the resulting file opens fine (with mesh node intact) in Creator. Stumped...


I've attached the sample source file for you to examine, check out.

Original Post by: SteveThompson Wed Sep 4 16:52:38 2013


I get a FLT file written out, but it doesn’t contain my mesh.

Since you say you don't have Creator... just curious how you tell the FLT file does not contain the mesh? I wonder if that program could be in error somehow?


For example, you are writing lat/lon values on the mesh vertices. If you inspect the mesh visually and the lat/lons are not converted properly you may not "see" the mesh node visually. In Creator the verts are interpreted as meters which makes your mesh "collapsed" on itself in XY plane. It has some Height variation but in Creator it looks like a tall, thin line so you may not "see" it visually.

Login to post a comment