Inexor
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
obj.hpp
Go to the documentation of this file.
1 #pragma once
3 
4 struct obj : vertmodel, vertloader<obj>
5 {
6  obj(const char *name) : vertmodel(name) {}
7 
8  static const char *formatname() { return "obj"; }
9  static bool animated() { return false; }
10  int type() const override { return MDL_OBJ; }
11 
12  struct objmeshgroup : vertmeshgroup
13  {
14  void parsevert(char *s, vector<vec> &out)
15  {
16  vec &v = out.add(vec(0, 0, 0));
17  while(isalpha(*s)) s++;
18  loopi(3)
19  {
20  v[i] = strtod(s, &s);
21  while(isspace(*s)) s++;
22  if(!*s) break;
23  }
24  }
25 
26  bool load(const char *filename, float smooth)
27  {
28  int len = strlen(filename);
29  if(len < 4 || strcasecmp(&filename[len-4], ".obj")) return false;
30 
31  stream *file = openfile(filename, "rb");
32  if(!file) return false;
33 
34  name = newstring(filename);
35 
36  numframes = 1;
37 
39  char buf[512];
40 
43  vector<tcvert> tcverts;
44  vector<tri> tris;
45 
46  #define STARTMESH do { \
47  vertmesh &m = *new vertmesh; \
48  m.group = this; \
49  m.name = meshname[0] ? newstring(meshname) : NULL; \
50  meshes.add(&m); \
51  curmesh = &m; \
52  verthash.clear(); \
53  verts.setsize(0); \
54  tcverts.setsize(0); \
55  tris.setsize(0); \
56  } while(0)
57 
58  #define FLUSHMESH do { \
59  curmesh->numverts = verts.length(); \
60  if(verts.length()) \
61  { \
62  curmesh->verts = new vert[verts.length()]; \
63  memcpy(curmesh->verts, verts.getbuf(), verts.length()*sizeof(vert)); \
64  curmesh->tcverts = new tcvert[verts.length()]; \
65  memcpy(curmesh->tcverts, tcverts.getbuf(), tcverts.length()*sizeof(tcvert)); \
66  } \
67  curmesh->numtris = tris.length(); \
68  if(tris.length()) \
69  { \
70  curmesh->tris = new tri[tris.length()]; \
71  memcpy(curmesh->tris, tris.getbuf(), tris.length()*sizeof(tri)); \
72  } \
73  if(attrib[2].empty()) \
74  { \
75  if(smooth <= 1) curmesh->smoothnorms(smooth); \
76  else curmesh->buildnorms(); \
77  } \
78  } while(0)
79 
80  string meshname = "";
81  vertmesh *curmesh = nullptr;
82  while(file->getline(buf, sizeof(buf)))
83  {
84  char *c = buf;
85  while(isspace(*c)) c++;
86  switch(*c)
87  {
88  case '#': continue;
89  case 'v':
90  if(isspace(c[1])) parsevert(c, attrib[0]);
91  else if(c[1]=='t') parsevert(c, attrib[1]);
92  else if(c[1]=='n') parsevert(c, attrib[2]);
93  break;
94  case 'g':
95  {
96  while(isalpha(*c)) c++;
97  while(isspace(*c)) c++;
98  char *name = c;
99  size_t namelen = strlen(name);
100  while(namelen > 0 && isspace(name[namelen-1])) namelen--;
101  copystring(meshname, name, min(namelen+1, sizeof(meshname)));
102 
103  if(curmesh) FLUSHMESH;
104  curmesh = nullptr;
105  break;
106  }
107  case 'f':
108  {
109  if(!curmesh) STARTMESH;
110  int v0 = -1, v1 = -1;
111  while(isalpha(*c)) c++;
112  for(;;)
113  {
114  while(isspace(*c)) c++;
115  if(!*c) break;
116  ivec vkey(-1, -1, -1);
117  loopi(3)
118  {
119  vkey[i] = strtol(c, &c, 10);
120  if(vkey[i] < 0) vkey[i] = attrib[i].length() + vkey[i];
121  else vkey[i]--;
122  if(!attrib[i].inrange(vkey[i])) vkey[i] = -1;
123  if(*c!='/') break;
124  c++;
125  }
126  int *index = verthash.access(vkey);
127  if(!index)
128  {
129  index = &verthash[vkey];
130  *index = verts.length();
131  vert &v = verts.add();
132  v.pos = vkey.x < 0 ? vec(0, 0, 0) : attrib[0][vkey.x];
133  v.pos = vec(v.pos.z, -v.pos.x, v.pos.y);
134  v.norm = vkey.z < 0 ? vec(0, 0, 0) : attrib[2][vkey.z];
135  v.norm = vec(v.norm.z, -v.norm.x, v.norm.y);
136  tcvert &tcv = tcverts.add();
137  tcv.tc = vkey.y < 0 ? vec2(0, 0) : vec2(attrib[1][vkey.y].x, 1-attrib[1][vkey.y].y);
138  }
139  if(v0 < 0) v0 = *index;
140  else if(v1 < 0) v1 = *index;
141  else
142  {
143  tri &t = tris.add();
144  t.vert[0] = ushort(*index);
145  t.vert[1] = ushort(v1);
146  t.vert[2] = ushort(v0);
147  v1 = *index;
148  }
149  }
150  break;
151  }
152  }
153  }
154 
155  if(curmesh) FLUSHMESH;
156 
157  delete file;
158 
159  return true;
160  }
161  };
162 
163  meshgroup *loadmeshes(const char *name, va_list args) override
164  {
165  objmeshgroup *group = new objmeshgroup;
166  if(!group->load(name, va_arg(args, double))) { delete group; return nullptr; }
167  return group;
168  }
169 
170  bool loaddefaultparts() override
171  {
172  part &mdl = addpart();
173  const char *pname = parentdir(name);
174  defformatstring(name1, "%s/%s/tris.obj", *modeldir, name);
175  mdl.meshes = sharemeshes(path(name1), 2.0);
176  if(!mdl.meshes)
177  {
178  defformatstring(name2, "%s/%s/tris.obj", *modeldir, pname); // try obj in parent folder (vert sharing)
179  mdl.meshes = sharemeshes(path(name2), 2.0);
180  if(!mdl.meshes) return false;
181  }
182  Texture *tex, *masks;
183  loadskin(name, pname, tex, masks);
184  mdl.initskins(tex, masks);
185  if(tex==notexture) Log.std->warn("could not load model skin for {}", name1);
186  return true;
187  }
188 
189  bool load() override
190  {
191  formatstring(dir, "%s/%s", *modeldir, name);
192  defformatstring(cfgname, "%s/%s/obj.cfg", *modeldir, name);
193 
194  loading = this;
196  if(execfile(cfgname, false) && parts.length()) // configured obj, will call the obj* commands below
197  {
199  loading = nullptr;
200  loopv(parts) if(!parts[i]->meshes) return false;
201  }
202  else // obj without configuration, try default tris and skin
203  {
205  loading = nullptr;
206  if(!loaddefaultparts()) return false;
207  }
208  translate.y = -translate.y;
209  loaded();
210  return true;
211  }
212 };
213 
215 
void loadskin(const char *dir, const char *altdir, Texture *&skin, Texture *&masks)
Definition: rendermodel.cpp:1088
part & addpart()
Definition: animmodel.hpp:1134
vec translate
Definition: model.hpp:46
Definition: obj.hpp:4
Vector template.
Definition: cube_vector.hpp:22
#define FLUSHMESH
virtual void loaded()
Definition: animmodel.hpp:1298
char * name
Definition: model.hpp:42
obj(const char *name)
Definition: obj.hpp:6
string cfgname
Definition: worldio.cpp:227
Definition: vertmodel.hpp:25
int identflags
Definition: command.cpp:41
void initskins(Texture *tex=notexture, Texture *masks=notexture, int limit=0)
Definition: animmodel.hpp:691
Definition: animmodel.hpp:465
bool execfile(const char *cfgfile, bool msg)
Definition: command.cpp:2262
static Logger std
Logger for everything not fitting elsewhere.
Definition: Logging.hpp:89
meshgroup * sharemeshes(const char *name,...)
Definition: animmodel.hpp:583
vec norm
Definition: vertmodel.hpp:8
void smooth()
Definition: octaedit.cpp:1942
meshgroup * meshes
Definition: animmodel.hpp:613
vec pos
Definition: vertmodel.hpp:8
2-dimensional float vectors
Definition: geom.hpp:38
bool load(const char *filename, float smooth)
Definition: obj.hpp:26
SharedVar< char * > modeldir
static obj * loading
Definition: animmodel.hpp:1396
int type() const override
Definition: obj.hpp:10
unsigned short ushort
Definition: cube_types.hpp:8
else loopi(numargs)
Definition: command.cpp:3019
static const char * formatname()
Definition: obj.hpp:8
GLuint index
Definition: glexts.hpp:412
vertcommands< obj > objcommands
Definition: obj.hpp:214
vec2 tc
Definition: vertmodel.hpp:12
Definition: model.hpp:11
T & add(const T &x)
Add new index to vector.
Definition: cube_vector.hpp:73
vector with 3 floats and some useful methods.
Definition: geom.hpp:110
char void formatstring(char(&d)[N], const char *fmt,...) PRINTFARGS(2
const T & min(const inexor::rpc::SharedVar< T > &a, const T &b)
Definition: SharedVar.hpp:210
inexor::util::log_manager Log
Definition: Logging.cpp:241
Definition: obj.hpp:12
char * path(char *s)
Modifies the input string to only contain slashes in the direction the platform allows.
Definition: stream.cpp:63
int length() const
return size of used memory
Definition: cube_vector.hpp:146
const char * parentdir(const char *filename)
Definition: stream.cpp:120
void t(T x, const char *cmp)
Definition: utilTest.cpp:52
Legacy file system streams.
Definition: stream.hpp:22
static aviwriter * file
Definition: movie.cpp:830
Definition: vertmodel.hpp:435
Definition: command.hpp:72
vector< part * > parts
Definition: animmodel.hpp:1118
static bool animated()
Definition: obj.hpp:9
Definition: vertmodel.hpp:6
struct sphere::vert * verts
char * copystring(char *d, const char *s, size_t len)
Definition: cube_tools.hpp:56
Definition: octarender.cpp:163
virtual bool getline(char *str, size_t len)
Definition: stream.cpp:318
Definition: animmodel.hpp:609
#define STARTMESH
static void attrib(T x)
Definition: glemu.hpp:106
Texture * notexture
Global used to specify this texture has not be found.
Definition: texture.cpp:266
GLsizei const GLuint GLenum pname
Definition: glexts.hpp:396
T * access(const U &key)
Definition: cube_hash.hpp:135
Definition: vertmodel.hpp:14
Definition: vertmodel.hpp:439
Definition: vertmodel.hpp:8
bool load() override
Definition: obj.hpp:189
meshgroup * loadmeshes(const char *name, va_list args) override
Definition: obj.hpp:163
bool loaddefaultparts() override
Definition: obj.hpp:170
void parsevert(char *s, vector< vec > &out)
Definition: obj.hpp:14
#define defformatstring(d,...)
Definition: cube_formatting.hpp:62
stream * openfile(const char *filename, const char *mode)
Definition: stream.cpp:907
3-dimensional INTEGER vectors
Definition: geom.hpp:1226
Definition: cube_hash.hpp:248
#define loopv(v)
Definition: cube_loops.hpp:21
char * newstring(size_t l)
Definition: cube_tools.hpp:71
static string dir
Definition: animmodel.hpp:1397
ushort vert[3]
Definition: vertmodel.hpp:14
A Texture entry, holding info about a texture on the GPU.
Definition: texture.hpp:27
Definition: vertmodel.hpp:12