1 registered members (AndrewAMD),
1,018
guests, and 6
spiders. |
Key:
Admin,
Global Mod,
Mod
|
|
|
Re: export all entities to obj
[Re: EpsiloN]
#458857
04/03/16 11:01
04/03/16 11:01
|
Joined: Dec 2011
Posts: 1,823 Netherlands
Reconnoiter
OP
Serious User
|
OP
Serious User
Joined: Dec 2011
Posts: 1,823
Netherlands
|
lol . That is pretty cool that you are making an animation system, does it work well? This kind of stuff can also be fun for adding modding support for games, so players can easily merge ingame models & attachments and than export/save it. (since .obj can also be used through ent_create) I only dont know if animation is supported for .obj, thought not iirc. I just got an idea to compare the .obj text exported by this code with working .obj text exported by model programs, that should give me some clues. (suprised I hadn't thought of this sooner) Also this seems like an interesting article ( http://paulbourke.net/dataformats/obj/) I am going to dig in a bit
Last edited by Reconnoiter; 04/03/16 11:03.
|
|
|
Re: export all entities to obj
[Re: Reconnoiter]
#458861
04/03/16 14:18
04/03/16 14:18
|
Joined: Jan 2006
Posts: 968
EpsiloN
User
|
User
Joined: Jan 2006
Posts: 968
|
Well, the system uses its own format (records directly bone orientation in Acknex) so its not tied to any model format. This is both good and bad, but it currently serves a different purpose than to animate models for games I do plan in the future to adapt it for models in games, because the user base of the program (lets hope its big) will create all kinds of animations and activities, which all will pass through approval, so they will definitely look good, and we'll all be able to use them in the future, even from different engines if all goes well... But that's the plan, not an all-in-one (super hard to use) package for animating everything, but a program crafted specifically for human animation with accurate joint constraints and a lot of built-in animations to tweak. I'm working with a Fitness Science Doctor on the body movement and constraints, so we can get the best out of this. And if you're planning on making a modeling & animation package for Acknex I'll be happy to share and help.
|
|
|
Re: export all entities to obj
[Re: EpsiloN]
#458866
04/03/16 16:17
04/03/16 16:17
|
Joined: Dec 2011
Posts: 1,823 Netherlands
Reconnoiter
OP
Serious User
|
OP
Serious User
Joined: Dec 2011
Posts: 1,823
Netherlands
|
I do plan in the future to adapt it for models in games, because the user base of the program (lets hope its big) will create all kinds of animations and activities, which all will pass through approval, so they will definitely look good, and we'll all be able to use them in the future, even from different engines if all goes well...
But that's the plan, not an all-in-one (super hard to use) package for animating everything, but a program crafted specifically for human animation with accurate joint constraints and a lot of built-in animations to tweak. , I would recommend trying to let it export to e.g. fbx. Possible buy such a plugin at a later stage, cause it will make your program alot more flexible. Also it is a good idea to indeed not make it an all-in-one tool but focus on a niche, like easy and funny way to animate stuff (I know I would atleast try it and perhaps even buy it , I hate the standard animating lol). And if you're planning on making a modeling & animation package for Acknex I'll be happy to share and help. , I am still working a bit on my map editor which I want to ship later with my games to extend modding / mapping capabilities, perhaps lateron I will try to add some simple modeling stuff to it easier set up props or such. Dunno yet. But I think this can be really powerfull stuff. For example, Unity editor also has a community plugin that allows you to model things inside your map and which is a great succes. -edit I know now that the faces are the culprit, so that is atleast one step closer to the right direction. Now the hard part, fixing it.
Last edited by Reconnoiter; 04/03/16 16:38.
|
|
|
Re: export all entities to obj
[Re: Reconnoiter]
#459106
04/22/16 13:15
04/22/16 13:15
|
Joined: Dec 2011
Posts: 1,823 Netherlands
Reconnoiter
OP
Serious User
|
OP
Serious User
Joined: Dec 2011
Posts: 1,823
Netherlands
|
update geometryForget a bit about this thread till today, so I decided to try it and again and now have the export of geometry of all the entities in a level to 1 obj file working. I also added the entities scales xyz and pos xyz. Note that while importing the obj in e.g. med or possible other programs, everything needs to be rotated by 90 or 180 or 270 degrees on xy rotation. But relative to each other, the objects should be positioned and rotated correctly. Code:
#include <acknex.h>
#include <default.c>
#include <d3d9.h>
#include <stdio.h>
void export_all_obj(ENTITY *entity, var scale)
{
STRING* name = str_create("#256");
STRING* objname = str_create("#256");
STRING* mtlname = str_create("#256");
int i;
var beginVertex = 0; //for entities past the first; vertex index is not reset between entities in same obj file
//get names for obj file
str_for_entfile(name, entity);
str_trunc(name, 4);
str_lwr(name);
str_cpy(objname, name);
str_cpy(mtlname, name);
str_cat(objname, ".obj");
str_cat(mtlname, ".mtl");
// //MATERIAL + SKINS (of given *entity)
// int numskins = ent_skins(entity);
// FILE *file = fopen(mtlname->chars, "w");
// for(i = 0; i < numskins; i++)
// {
// fprintf(file, "newmtl material%d\n", i);
// BMAP *b = bmap_for_entity(entity, i + 1);
// if(b)
// {
// char s[80];
// sprintf(s, "%s%d.bmp", name->chars, i);
// bmap_save(b, s);
// fprintf(file, "map_Kd %s\n", s);
// }
// fprintf(file, "\n");
// }
// fclose(file);
//MODEL (geometry of all entities)
FILE *file = fopen(objname->chars, "w");
for(you = ent_next(NULL); you; you = ent_next(you))
{
//get names
str_for_entfile(name, entity);
str_trunc(name, 4);
str_lwr(name);
str_cpy(mtlname, name);
str_cat(mtlname, ".mtl");
LPD3DXMESH mesh = (LPD3DXMESH)ent_getmesh(you, 0, 0);
int numvertices = mesh->GetNumVertices();
int numfaces = mesh->GetNumFaces();
//add object info
fprintf(file, "mtllib %s\n", mtlname->chars);
fprintf(file, "o %s\n", name->chars);
D3DVERTEX *vb; mesh->LockVertexBuffer(0, (void**)&vb);
WORD *ib; mesh->LockIndexBuffer(0, (void**)&ib);
DWORD *ab; mesh->LockAttributeBuffer(0, &ab);
for(i = 0; i < numvertices; i++)
fprintf(file, "v %f %f %f\n",
-(double)((vb[i].x + you.x) * you.scale_x * scale), (double)((vb[i].y + you.z) * you.scale_z * scale), (double)((vb[i].z + you.y) * you.scale_y * scale));
for(i = 0; i < numvertices; i++)
fprintf(file, "vt %f %f\n", (double)vb[i].u1, 1 - (double)vb[i].v1);
for(i = 0; i < numvertices; i++)
fprintf(file, "vn %f %f %f\n", -(double)vb[i].nx, (double)vb[i].ny, (double)vb[i].nz);
fprintf(file, "s on\n");
int material, a, b, c;
int previousmaterial = -999;
for(i = 0; i < numfaces; i++)
{
material = ab[i];
if(material != previousmaterial)
fprintf(file, "usemtl material%d\n", material);
previousmaterial = material;
a = ib[i*3+2] + 1 + beginVertex;
b = ib[i*3+1] + 1 + beginVertex;
c = ib[i*3+0] + 1 + beginVertex;
fprintf(file, "f %d/%d/%d %d/%d/%d %d/%d/%d\n", a, a, a, b, b, b, c, c, c);
}
mesh->UnlockVertexBuffer();
mesh->UnlockIndexBuffer();
mesh->UnlockAttributeBuffer();
beginVertex += numvertices; //for next entities faces
}
fclose(file);
str_remove(name);
str_remove(objname);
str_remove(mtlname);
}
Call it through "export_all_obj(entitypointer, scale);" without the quotes and for entitypointer use the pointer to the entity you want for the name of the file. So e.g. if write "player" there (without the quotes) and the player entity's modelfile name is called player.mdl, the obj file is named player.obj. And for "scale" type in some number depending on how small or big you want the obj file in other programs. If you dont know what to choose here, just type in 1. Note: the exported mesh appears to be not always closed. So far it seems to be non-closed for higher poly models but I need to check that to be sure. Note2: this is only geometry, not yet skins and materials.
Last edited by Reconnoiter; 04/22/16 13:17.
|
|
|
Re: export all entities to obj
[Re: Dooley]
#459783
06/04/16 09:02
06/04/16 09:02
|
Joined: Dec 2011
Posts: 1,823 Netherlands
Reconnoiter
OP
Serious User
|
OP
Serious User
Joined: Dec 2011
Posts: 1,823
Netherlands
|
Hi Dooley, Sure post it here, can't hurt. Maybe it can solve the non-closed mesh problem. Although the inclusion of skin+material on expert shouldn't be to hard to implement in, for me currently it has low priority. But if anyone would find it usefull, I can add it someday. I used the MED export to ASCII to look at what the file should look like. I'm guessing you could do the same with an .obj file. One important thing I learned, is that you have to view the file in a hex editor, not just notepad. It had a bunch of otherwise invisible characters that it required for MED to read it properly. , tried that before, but found it easier to just read about how obj works.
|
|
|
Re: export all entities to obj
[Re: Reconnoiter]
#459893
06/10/16 09:32
06/10/16 09:32
|
Joined: May 2005
Posts: 868 Chicago, IL
Dooley
User
|
User
Joined: May 2005
Posts: 868
Chicago, IL
|
This function writes all the vertices (made up of several repeated models) into a text file... function write_segment_file() { // wait(1); // return; var file_handle = file_open_append("anomaly_model.txt"); var seg_loc = 1; float cx; float cy; float cz; // file_str_write(file_handle,"test"); VECTOR seg_vec; vec_zero(seg_vec); while(seg_loc <= ent_vertices(my))//checks if current vertex exists { vec_for_vertex (seg_vec,my,seg_loc); cx = seg_vec.x; cy = seg_vec.y; cz = seg_vec.z; file_asc_write(file_handle,10);//line feed file_var_write(file_handle,cx); file_var_write(file_handle,cy); file_var_write(file_handle,cz); file_str_write(file_handle,";"); seg_loc += 1; wait(1); } file_close(file_handle); segments_written += 1;//counts up to total_segments }
This one then writes all the triangles, based on the original model's ascii file that I got with MED. It has to add the total number of vertices (skill3) to the base number for it to work as one big model. function write_triangle_file() { var file_handle = file_open_append("anomaly_model.txt"); var total_tris = ent_status(my,4); var tri_loc = 0;
while(tri_loc <= total_tris)// { file_asc_write(file_handle,10);//line feed if(tri_loc == 0) { tri_1 = 2 + my.skill3; tri_2 = 1 + my.skill3; tri_3 = 0 + my.skill3; } if(tri_loc == 1) { tri_1 = 3 + my.skill3; tri_2 = 2 + my.skill3; tri_3 = 0 + my.skill3; } if(tri_loc == 2) { tri_1 = 4 + my.skill3; tri_2 = 7 + my.skill3; tri_3 = 6 + my.skill3; } if(tri_loc == 3) { tri_1 = 5 + my.skill3; tri_2 = 4 + my.skill3; tri_3 = 6 + my.skill3; } if(tri_loc == 4) { tri_1 = 8 + my.skill3; tri_2 = 11 + my.skill3; tri_3 = 10 + my.skill3; } if(tri_loc == 5) { tri_1 = 9 + my.skill3; tri_2 = 8 + my.skill3; tri_3 = 10 + my.skill3; } if(tri_loc == 6) { tri_1 = 12 + my.skill3; tri_2 = 15 + my.skill3; tri_3 = 14 + my.skill3; } if(tri_loc == 7) { tri_1 = 13 + my.skill3; tri_2 = 12 + my.skill3; tri_3 = 14 + my.skill3; } if(tri_loc == 8) { tri_1 = 16 + my.skill3; tri_2 = 19 + my.skill3; tri_3 = 18 + my.skill3; } if(tri_loc == 9) { tri_1 = 17 + my.skill3; tri_2 = 16 + my.skill3; tri_3 = 18 + my.skill3; } if(tri_loc == 10) { tri_1 = 20 + my.skill3; tri_2 = 23 + my.skill3; tri_3 = 22 + my.skill3; } if(tri_loc == 11) { tri_1 = 21 + my.skill3; tri_2 = 20 + my.skill3; tri_3 = 22 + my.skill3; } if(tri_loc == 12) { tri_1 = 16 + my.skill3; tri_2 = 17 + my.skill3; tri_3 = 0 + my.skill3; } if(tri_loc == 13) { tri_1 = 1 + my.skill3; tri_2 = 16 + my.skill3; tri_3 = 0 + my.skill3; } if(tri_loc == 14) { tri_1 = 11 + my.skill3; tri_2 = 8 + my.skill3; tri_3 = 1 + my.skill3; } if(tri_loc == 15) { tri_1 = 2 + my.skill3; tri_2 = 11 + my.skill3; tri_3 = 1 + my.skill3; } if(tri_loc == 16) { tri_1 = 3 + my.skill3; tri_2 = 0 + my.skill3; tri_3 = 13 + my.skill3; } if(tri_loc == 17) { tri_1 = 14 + my.skill3; tri_2 = 3 + my.skill3; tri_3 = 13 + my.skill3; } if(tri_loc == 18) { tri_1 = 2 + my.skill3; tri_2 = 3 + my.skill3; tri_3 = 20 + my.skill3; } if(tri_loc == 19) { tri_1 = 21 + my.skill3; tri_2 = 2 + my.skill3; tri_3 = 20 + my.skill3; } if(tri_loc == 20) { tri_1 = 4 + my.skill3; tri_2 = 5 + my.skill3; tri_3 = 18 + my.skill3; } if(tri_loc == 21) { tri_1 = 19 + my.skill3; tri_2 = 4 + my.skill3; tri_3 = 18 + my.skill3; } if(tri_loc == 22) { tri_1 = 15 + my.skill3; tri_2 = 12 + my.skill3; tri_3 = 5 + my.skill3; } if(tri_loc == 23) { tri_1 = 6 + my.skill3; tri_2 = 15 + my.skill3; tri_3 = 5 + my.skill3; } if(tri_loc == 24) { tri_1 = 9 + my.skill3; tri_2 = 10 + my.skill3; tri_3 = 7 + my.skill3; } if(tri_loc == 25) { tri_1 = 4 + my.skill3; tri_2 = 9 + my.skill3; tri_3 = 7 + my.skill3; } if(tri_loc == 26) { tri_1 = 6 + my.skill3; tri_2 = 7 + my.skill3; tri_3 = 22 + my.skill3; } if(tri_loc == 27) { tri_1 = 23 + my.skill3; tri_2 = 6 + my.skill3; tri_3 = 22 + my.skill3; } if(tri_loc == 28) { tri_1 = 19 + my.skill3; tri_2 = 16 + my.skill3; tri_3 = 8 + my.skill3; } if(tri_loc == 29) { tri_1 = 9 + my.skill3; tri_2 = 19 + my.skill3; tri_3 = 8 + my.skill3; } if(tri_loc == 30) { tri_1 = 21 + my.skill3; tri_2 = 22 + my.skill3; tri_3 = 10 + my.skill3; } if(tri_loc == 31) { tri_1 = 11 + my.skill3; tri_2 = 21 + my.skill3; tri_3 = 10 + my.skill3; } if(tri_loc == 32) { tri_1 = 17 + my.skill3; tri_2 = 18 + my.skill3; tri_3 = 12 + my.skill3; } if(tri_loc == 33) { tri_1 = 13 + my.skill3; tri_2 = 17 + my.skill3; tri_3 = 12 + my.skill3; } if(tri_loc == 34) { tri_1 = 23 + my.skill3; tri_2 = 20 + my.skill3; tri_3 = 14 + my.skill3; } if(tri_loc == 35) { tri_1 = 15 + my.skill3; tri_2 = 23 + my.skill3; tri_3 = 14 + my.skill3; } if(tri_loc == 36) { tri_1 = 17 + my.skill3; tri_2 = 13 + my.skill3; tri_3 = 0 + my.skill3; } if(tri_loc == 37) { tri_1 = 21 + my.skill3; tri_2 = 11 + my.skill3; tri_3 = 2 + my.skill3; } if(tri_loc == 38) { tri_1 = 23 + my.skill3; tri_2 = 15 + my.skill3; tri_3 = 6 + my.skill3; } if(tri_loc == 39) { tri_1 = 19 + my.skill3; tri_2 = 9 + my.skill3; tri_3 = 4 + my.skill3; } if(tri_loc == 40) { tri_1 = 12 + my.skill3; tri_2 = 18 + my.skill3; tri_3 = 5 + my.skill3; } if(tri_loc == 41) { tri_1 = 14 + my.skill3; tri_2 = 20 + my.skill3; tri_3 = 3 + my.skill3; } if(tri_loc == 42) { tri_1 = 10 + my.skill3; tri_2 = 22 + my.skill3; tri_3 = 7 + my.skill3; } if(tri_loc == 43) { tri_1 = 8 + my.skill3; tri_2 = 16 + my.skill3; tri_3 = 1 + my.skill3; } file_var_write(file_handle,tri_1); file_var_write(file_handle,tri_2); file_var_write(file_handle,tri_3); file_str_write(file_handle,";"); tri_loc += 1; wait(1); } file_close(file_handle); }
There's one other function that comes before these two, it sets up the file and writes the beginning parts: function write_export_file() { //HERE IT WILL OPEN FILE AND WRITE IN TOTAL NUMBER OF VERTICES////////////////////////////////////////////////////////////////////////////// var file_handle = file_open_append("anomaly_model.txt");//opens file to write anomaly model file_var_write(file_handle,vertex_total);//vertex_total will be inserted after file header file_asc_write(file_handle,59);//; file_close(file_handle); wait(1);//waits until vertex_total is written write_start = 1;//begin writing segment data to file while(segments_written < total_segments) { //waits until all segments have written their data to export file wait(1); } file_handle = file_open_append("anomaly_model.txt");//opens file to write anomaly model // Once all vertices are written, write the file closing text file_asc_write(file_handle,10);//line feed file_asc_write(file_handle,10);//line feed file_asc_write(file_handle,84);//T file_asc_write(file_handle,114);//r file_asc_write(file_handle,105);//i file_asc_write(file_handle,97);//a file_asc_write(file_handle,110);//n file_asc_write(file_handle,103);//g file_asc_write(file_handle,108);//l file_asc_write(file_handle,101);//e file_asc_write(file_handle,115);//s file_asc_write(file_handle,58);//: file_asc_write(file_handle,32);//space // file_asc_write(file_handle,48);//0
file_var_write(file_handle,total_triangles);//writes total number of triangles to the export file
file_asc_write(file_handle,59);//; file_close(file_handle); wait(1);//waits until vertex_total is written write_triangles = 1;//begin writing segment data to file //write triangles while(triangles_written <= total_triangles) { //waits until all segments have written their data to export file wait(1); } file_handle = file_open_append("anomaly_model.txt");//writes the last bit of closing info file_asc_write(file_handle,10);//line feed file_asc_write(file_handle,125);//close parenthesis file_asc_write(file_handle,59);//; file_asc_write(file_handle,10);//line feed file_asc_write(file_handle,10);//line feed file_asc_write(file_handle,10);//line feed //then close the file file_close(file_handle); }
Also, in each segment entity, there is a while loop. In this loop, it checks if the "write_start" variable has been changed to 1, which is done in the "write_export_file" function above... if(write_start == 1 && my.skill2 == 0) { write_segment_file();//writes the coordinates for this anomaly to a file my.skill2 = 1;//prevents this segment from writing its data more than once } if(write_triangles == 1 && my.skill2 == 1) { write_triangle_file();//write the segments triangle data to file my.skill2 = 2;//prevents this segment from writing triangles more than once }
And one more thing, before the while loop, each segment entity sets up it's parameters like this: total_segments += 1;//used by model export to determine total number of segments that need to be written my.skill3 = vertex_total;//sets the current vertex number for exported file total_triangles += ent_status(my,4); vertex_total += ent_vertices(my);//add this segments number of vertices to the total count
Sorry if this is confusing. It does work, and I was able to export my "Anomalies" and even upload them to Sketchfab, and Shapeways for 3D printing. If here's an easier way to do it, I'd love to hear about it. You can see the results here: http://www.schmidt-gallery.com/3D.html
Last edited by Dooley; 06/10/16 09:34.
|
|
|
|