OpenGL ES SDK for Android ARM Developer Center
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
model3d.cpp
Go to the documentation of this file.
1 /* Copyright (c) 2017, ARM Limited and Contributors
2  *
3  * SPDX-License-Identifier: MIT
4  *
5  * Permission is hereby granted, free of charge,
6  * to any person obtaining a copy of this software and associated documentation files (the "Software"),
7  * to deal in the Software without restriction, including without limitation the rights to
8  * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software,
9  * and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
10  *
11  * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
12  *
13  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
14  * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
16  * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
17  * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
19  */
20 
21 #include <model3d.h>
22 #include <android/log.h>
23 #define LOG_TAG "Asset_Loader"
24 #define LOGI(...) __android_log_print(ANDROID_LOG_INFO, LOG_TAG, __VA_ARGS__)
25 #define LOGE(...) __android_log_print(ANDROID_LOG_ERROR, LOG_TAG, __VA_ARGS__)
26 
27 
28 #include <iostream>
29 #include <fstream>
30 
31 namespace Model3D
32 {
33  bool load_file(const std::string& a_path, char **a_buffer, int &a_bytes_read, const bool binary)
34  {
35  std::fstream file;
36  if(binary)
37  file.open(a_path.c_str(), std::ios::in | std::ios::binary);
38  else
39  file.open( a_path.c_str(), std::ios::in );
40 
41  if (!file.is_open())
42  {
43  LOGE("Error! opening file %s", a_path.c_str());
44  return false;
45  }
46 
47  file.seekg(0, std::ios_base::end);
48  size_t file_size = file.tellg();
49  file.seekg(0, std::ios_base::beg);
50 
51  if(file_size == 0)
52  {
53  LOGE( "Error! reading file size %s ", a_path.c_str());
54  return false;
55  }
56 
57  *a_buffer = new char[file_size];
58 
59  if(*a_buffer == NULL)
60  {
61  LOGE( "Error! Out of memory allocating *a_buffer");
62  return false;
63  }
64 
65  file.read(*a_buffer, file_size);
66  file.close();
67 
68  a_bytes_read = static_cast<int>(file_size);
69 
70  return true;
71  }
72 
74  {
75  this->m_ambient = NULL;
76  this->m_diffuse = NULL;
77  this->m_specular = NULL;
78  this->m_emmision = NULL;
79  this->m_shine = NULL;
80  this->m_transparency = NULL;
81  }
82 
84  {
85  this->m_ambient = NULL;
86  this->m_diffuse = NULL;
87  this->m_specular = NULL;
88  this->m_emmision = NULL;
89  this->m_shine = NULL;
90  this->m_transparency = NULL;
91  }
92 
94  {
95  this->m_time = NULL;
96  this->m_transforms = NULL;
97  }
98 
100  {
101  this->m_time = NULL;
102  this->m_transforms = NULL;
103  }
104 
106  {
107  this->m_has_animation = false;
108  this->m_has_materials = false;
109  this->m_has_indices = false;
110  this->m_has_normals = false;
111  this->m_has_texture_coordinates0 = false;
112 
113  this->m_vertices_count = NULL;
114  this->m_indices_count = NULL;
115  this->m_bones_count = NULL;
116  this->m_keyframes_count = NULL;
117  this->m_materials_count = NULL;
118 
119  this->m_positions = NULL;
120  this->m_texture_coordinates0 = NULL;
121  this->m_normals = NULL;
122  this->m_bone_ids = NULL;
123  this->m_weights = NULL;
124  this->m_materials = NULL;
125  this->m_indices = NULL;
126  this->m_keyframes = NULL;
127 
128  this->m_geometry_buffer = NULL;
129  this->m_tangent_buffer = NULL;
130  this->m_animation_buffer = NULL;
131 
132  this->m_bounding_box_minimum = NULL;
133  this->m_bounding_box_maximum = NULL;
134  }
135 
136  Model3D::~Model3D()
137  {
138  if (this->m_has_materials)
139  {
140  for (unsigned int i = 0; i < *this->m_materials_count; ++i)
141  {
142  delete this->m_materials[i];
143  }
144  delete[] this->m_materials;
145  }
146 
147  if (this->m_has_animation)
148  {
149  for (unsigned int i = 0; i < *this->m_keyframes_count; ++i)
150  {
151  delete this->m_keyframes[i];
152  }
153  delete[] this->m_keyframes;
154  }
155 
156  this->m_vertices_count = NULL;
157  this->m_indices_count = NULL;
158  this->m_bones_count = NULL;
159  this->m_keyframes_count = NULL;
160  this->m_materials_count = NULL;
161 
162  this->m_positions = NULL;
163  this->m_texture_coordinates0 = NULL;
164  this->m_normals = NULL;
165  this->m_bone_ids = NULL;
166  this->m_weights = NULL;
167  this->m_materials = NULL;
168  this->m_indices = NULL;
169  this->m_keyframes = NULL;
170 
171  this->m_bounding_box_minimum = NULL;
172  this->m_bounding_box_maximum = NULL;
173 
174  delete[] this->m_geometry_buffer;
175  delete[] this->m_tangent_buffer;
176  delete[] this->m_animation_buffer;
177 
178  this->m_geometry_buffer = NULL;
179  this->m_tangent_buffer = NULL;
180  this->m_animation_buffer = NULL;
181  }
182 
183  bool Model3D::load(const std::string& a_path)
184  {
185  int bytes_read;
186  if (!load_file(a_path, &this->m_geometry_buffer, bytes_read))
187  {
188  LOGE("Error! opening geometry file %s", a_path.c_str());
189  return false;
190  }
191 
192  char *buffer = this->m_geometry_buffer;
193 
194  // test the magic_id for 'geom'
195  if (buffer[0] != 'g' ||
196  buffer[1] != 'e' ||
197  buffer[2] != 'o' ||
198  buffer[3] != 'm')
199  {
200  LOGE( "%s is not a valid 'geom' file", a_path.c_str() );
201  delete []this->m_geometry_buffer;
202  return false;
203  }
204 
205  buffer += sizeof(unsigned int);
206 
207  this->m_has_indices = *((unsigned int*)buffer) & 1;
208  this->m_has_texture_coordinates0 = *((unsigned int*)buffer) & (1 << 8);
209  this->m_has_materials = *((unsigned int*)buffer) & (1 << 12);
210  this->m_has_normals = *((unsigned int*)buffer) & (1 << 16);
211  this->m_has_animation = *((unsigned int*)buffer) & (1 << 24);
212 
213  buffer += sizeof(unsigned int);
214 
215  buffer += sizeof( float ) * 16 ;
216 
217  // Read bounding box
218  this->m_bounding_box_minimum = (float*)buffer;
219  buffer += (sizeof(float) * 3);
220  this->m_bounding_box_maximum = (float*)buffer;
221  buffer += (sizeof(float) * 3);
222 
223  // Read vertices count
224  this->m_vertices_count = (unsigned int*) buffer;
225  buffer += sizeof(unsigned int);
226  this->m_positions = (float*)buffer;
227  buffer += (sizeof(float) * 3 * (*this->m_vertices_count));
228 
229  LOGI( "Vx count=%u", *this->m_vertices_count );
230 
231  // If texture coordinates exist with this geometry then set the pointers
232  if (this->m_has_texture_coordinates0)
233  {
234  this->m_texture_coordinates0 = (float*)buffer;
235  buffer += (sizeof(float) * 3 * (*this->m_vertices_count));
236  }
237 
238  // If normals exist with this geometry then load it
239  if (this->m_has_normals)
240  {
241  this->m_normals = (float*)buffer;
242  buffer += (sizeof(float) * 3 * (*this->m_vertices_count));
243  }
244 
245  // If animation exists then it must have bone ids and vertex weights we need to load that
246  if (this->m_has_animation)
247  {
248  // Bone Ids
249  this->m_bone_ids = (unsigned int*)buffer;
250  buffer += (sizeof(unsigned int) * 4 * (*this->m_vertices_count));
251 
252  // Vertex Weights
253  this->m_weights = (float*)buffer;
254  buffer += (sizeof(float) * 4 * (*this->m_vertices_count));
255  }
256 
257  // If the data is indexed then load set the pointers
258  if (this->m_has_indices)
259  {
260  this->m_indices_count = (unsigned int*)buffer;
261  buffer += sizeof(unsigned int);
262  this->m_indices = (unsigned int*)buffer;
263  buffer += (sizeof(unsigned int) * 3 * (*this->m_indices_count));
264  }
265 
266  // If there are materials we need to set the pointers
267  if (this->m_has_materials)
268  {
269  this->m_materials_count = (unsigned int*)buffer;
270  buffer += sizeof(unsigned int);
271 
272  this->m_materials = new Material*[*this->m_materials_count];
273 
274  for (unsigned int i = 0; i < *this->m_materials_count; ++i)
275  {
276  this->m_materials[i] = new Material();
277 
278  this->m_materials[i]->m_ambient = (float*)buffer; buffer += (sizeof(float) * 4);
279  this->m_materials[i]->m_diffuse = (float*)buffer; buffer += (sizeof(float) * 4);
280  this->m_materials[i]->m_specular = (float*)buffer; buffer += (sizeof(float) * 4);
281  this->m_materials[i]->m_emmision = (float*)buffer; buffer += (sizeof(float) * 4);
282  this->m_materials[i]->m_shine = (float*)buffer; buffer += sizeof(float);
283  this->m_materials[i]->m_transparency = (float*)buffer; buffer += sizeof(float);
284  }
285  }
286 
287  // Read bitangents from file
288  if ( this->m_has_normals && this->m_has_texture_coordinates0 )
289  {
290  int bytes_read_tan;
291  if ( !load_file( a_path + "tan", &this->m_tangent_buffer, bytes_read_tan ) )
292  {
293  LOGE( "Error! opening tangent file %s", (a_path + "tan").c_str() );
294  return false;
295  }
296 
297  char *bufferTan = this->m_tangent_buffer;
298 
299  // test the magic_id for 'geomtan'
300  if ( bufferTan[0] != 'g' ||
301  bufferTan[1] != 'e' ||
302  bufferTan[2] != 'o' ||
303  bufferTan[3] != 'm' ||
304  bufferTan[4] != 't' ||
305  bufferTan[5] != 'a' ||
306  bufferTan[6] != 'n' )
307  {
308  LOGE( "%s is not a valid 'geomtan' file", (a_path + "tan").c_str() );
309  delete[]this->m_tangent_buffer;
310  return false;
311  }
312 
313  bufferTan += 7;
314  this->m_tangents = (float*) bufferTan;
315  }
316  LOGI("Finished loading");
317 
318  // If animation exists with this geometry then set the pointers
319  if (this->m_has_animation)
320  {
321  // This assumes the animation file is the same name but instead of .geom the extension is .anim
322  std::string animation_filename = a_path.substr(0, a_path.length() - 5);
323  animation_filename = animation_filename.append(".anim");
324 
325  if (!load_file(animation_filename, &this->m_animation_buffer, bytes_read))
326  {
327  LOGE( "Error! opening animation file %s", animation_filename.c_str());
328  return false;
329  }
330 
331  char *buffer = this->m_animation_buffer;
332 
333  // test the magic_id for 'anim'
334  if (buffer[0] != 'a' ||
335  buffer[1] != 'n' ||
336  buffer[2] != 'i' ||
337  buffer[3] != 'm')
338  {
339  LOGE( "%s is not a valid 'anim' file", a_path.c_str());
340  delete []this->m_animation_buffer;
341  return false;
342  }
343 
344  buffer += sizeof(unsigned int);
345 
346  // Set bones count
347  this->m_bones_count = (unsigned int*)buffer;
348  buffer += sizeof(unsigned int);
349 
350  // Set keyframes count
351  this->m_keyframes_count = (unsigned int*)buffer;
352  buffer += sizeof(unsigned int);
353 
354  this->m_keyframes = new Keyframe*[*this->m_keyframes_count];
355  char *transforms_buffer = buffer + (*this->m_keyframes_count * sizeof(float));
356 
357  for (unsigned int i = 0; i < *this->m_keyframes_count; ++i)
358  {
359  this->m_keyframes[i] = new Keyframe();
360  this->m_keyframes[i]->m_time = (float*)buffer;
361  this->m_keyframes[i]->m_transforms = (float*)transforms_buffer;
362 
363  buffer += sizeof(float);
364  transforms_buffer += sizeof(float) * 16 * (*this->m_bones_count);
365  }
366  }
367  LOGI( "Here" );
368 
369  return true;
370  }
371 
372  unsigned int Model3D::get_indices_count() const
373  {
374  return *this->m_indices_count;
375  }
376 
377  unsigned int Model3D::get_keyframes_count() const
378  {
379  return *this->m_keyframes_count;
380  }
381 
382  float* Model3D::get_positions() const
383  {
384  return this->m_positions;
385  }
386 
387  float* Model3D::get_normals() const
388  {
389  return this->m_normals;
390  }
391 
392  float* Model3D::get_texture_coordinates0() const
393  {
394  return this->m_texture_coordinates0;
395  }
396 
397  float* Model3D::get_tangents() const
398  {
399  return this->m_tangents;
400  }
401 
402  unsigned int* Model3D::get_indices() const
403  {
404  return this->m_indices;
405  }
406 }
GLuint GLuint end
Definition: gl2ext.h:323
float * m_transforms
Transformations for all the bones in the current keyframe.
Definition: model3d.h:98
precision highp int
Definition: hiz_cull.cs:38
#define LOGI(...)
Definition: model3d.cpp:24
float * m_ambient
4D Ambient color of the material
Definition: model3d.h:68
#define LOGE(...)
Definition: model3d.cpp:25
GLsizei GLsizei GLenum void * binary
Definition: gl2ext.h:396
float * m_transparency
Transparency of the material.
Definition: model3d.h:73
bool load_file(const std::string &a_path, char **a_buffer, int &a_bytes_read, const bool binary)
Definition: model3d.cpp:33
float * m_shine
Shine exponent of the material.
Definition: model3d.h:72
float * m_diffuse
4D Diffuse color of the material
Definition: model3d.h:69
float * m_specular
4D Specular color of the material
Definition: model3d.h:70
GLenum GLuint buffer
Definition: gl2ext.h:628
float * m_time
Keyframe time in seconds for the all the bones.
Definition: model3d.h:97
float * m_emmision
4D Emissive color of the material
Definition: model3d.h:71
precision highp float
Definition: hiz_cull.cs:37