zenilib  0.5.3.0
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Groups Pages
Vertex_Buffer.cpp
Go to the documentation of this file.
1 /* This file is part of the Zenipex Library (zenilib).
2  * Copyright (C) 2011 Mitchell Keith Bloch (bazald).
3  *
4  * zenilib is free software: you can redistribute it and/or modify
5  * it under the terms of the GNU Lesser General Public License as published by
6  * the Free Software Foundation, either version 3 of the License, or
7  * (at your option) any later version.
8  *
9  * zenilib is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12  * GNU Lesser General Public License for more details.
13  *
14  * You should have received a copy of the GNU Lesser General Public License
15  * along with zenilib. If not, see <http://www.gnu.org/licenses/>.
16  */
17 
18 #include <zeni_graphics.h>
19 
20 #include <algorithm>
21 
22 #ifndef DISABLE_DX9
23 #include <d3dx9.h>
24 #endif
25 
26 //#define DISABLE_VBO
27 
28 #include <Zeni/Define.h>
29 
30 #if defined(_DEBUG) && defined(_WINDOWS)
31 #define DEBUG_NEW new(_NORMAL_BLOCK, __FILE__, __LINE__)
32 #define new DEBUG_NEW
33 #endif
34 
35 namespace Zeni {
36 
38  microrenderer();
39  }
40 
41  Vertex_Buffer_Renderer::Vertex_Buffer_Renderer(Vertex_Buffer &vertex_buffer)
42  : m_vbo(vertex_buffer)
43  {
44  }
45 
46  Vertex_Buffer::Vertex_Buffer_Range::Vertex_Buffer_Range(Material * const &m, const size_t &s, const size_t &ne)
47  : material(m),
48  start(s),
49  num_elements(ne)
50  {
51  }
52 
54  : m_align_normals(false),
55  m_renderer(0),
56  m_prerendered(false),
57  m_macrorenderer(new Vertex_Buffer_Macrorenderer)
58  {
59  get_vbos().insert(this);
60  }
61 
62  template <typename VERTEX>
63  static void clear_triangles(std::vector<Triangle<VERTEX> *> &triangles, std::vector<Vertex_Buffer::Vertex_Buffer_Range *> &descriptors) {
64  for(typename std::vector<Triangle<VERTEX> *>::iterator it = triangles.begin(), iend = triangles.end(); it != iend; ++it)
65  delete *it;
66  triangles.clear();
67 
68  for(std::vector<Vertex_Buffer::Vertex_Buffer_Range *>::iterator it = descriptors.begin(), iend = descriptors.end(); it != iend; ++it)
69  delete *it;
70  descriptors.clear();
71  }
72 
74  clear_triangles(m_triangles_cm, m_descriptors_cm);
75  clear_triangles(m_triangles_t, m_descriptors_t);
76 
77  delete m_renderer;
78  delete m_macrorenderer;
79 
80  get_vbos().erase(this);
81  }
82 
84  std::auto_ptr<Renderable> to_delete(triangle);
85  fax_Triangle(triangle);
86  }
87 
88  void Vertex_Buffer::fax_Triangle(const Triangle<Vertex2f_Color> * const &triangle) {
89  if(!triangle)
90  throw VBuf_Init_Failure();
91 
92  const Vertex2f_Color &v0 = triangle->a;
93  const Vertex2f_Color &v1 = triangle->b;
94  const Vertex2f_Color &v2 = triangle->c;
95 
99  facsimile.fax_Material(triangle->get_Material());
100 
101  fax_Triangle(&facsimile);
102  }
103 
105  std::auto_ptr<Renderable> to_delete(triangle);
106  fax_Triangle(triangle);
107  }
108 
110  if(!triangle)
111  throw VBuf_Init_Failure();
112 
113  const Vertex2f_Texture &v0 = triangle->a;
114  const Vertex2f_Texture &v1 = triangle->b;
115  const Vertex2f_Texture &v2 = triangle->c;
116 
120  facsimile.fax_Material(triangle->get_Material());
121 
122  fax_Triangle(&facsimile);
123  }
124 
126  std::auto_ptr<Renderable> to_delete(quad);
127  fax_Quadrilateral(quad);
128  }
129 
131  if(!quad)
132  throw VBuf_Init_Failure();
133 
136  }
137 
139  std::auto_ptr<Renderable> to_delete(quad);
140  fax_Quadrilateral(quad);
141  }
142 
144  if(!quad)
145  throw VBuf_Init_Failure();
146 
149  }
150 
152  if(!triangle)
153  throw VBuf_Init_Failure();
154 
155  if(!triangle->get_Material() ||
156  triangle->get_Material()->get_Texture().empty())
157  {
158  m_triangles_cm.push_back(triangle);
159  unprerender();
160  }
161  else {
162  delete triangle;
163  throw VBuf_Init_Failure();
164  }
165  }
166 
168  if(!triangle)
169  throw VBuf_Init_Failure();
170 
171  give_Triangle(triangle->get_duplicate());
172  }
173 
175  if(!triangle)
176  throw VBuf_Init_Failure();
177 
178  if(triangle->get_Material() &&
179  !triangle->get_Material()->get_Texture().empty())
180  {
181  m_triangles_t.push_back(triangle);
182  unprerender();
183  }
184  else {
185  delete triangle;
186  throw VBuf_Init_Failure();
187  }
188  }
189 
191  if(!triangle)
192  throw VBuf_Init_Failure();
193 
194  give_Triangle(triangle->get_duplicate());
195  }
196 
198  std::auto_ptr<Renderable> to_delete(quad);
199  fax_Quadrilateral(quad);
200  }
201 
203  if(!quad)
204  throw VBuf_Init_Failure();
205 
208  }
209 
211  std::auto_ptr<Renderable> to_delete(quad);
212  fax_Quadrilateral(quad);
213  }
214 
216  if(!quad)
217  throw VBuf_Init_Failure();
218 
221  }
222 
224  for(unsigned int i = 0; i < m_triangles_cm.size(); ++i)
225  get_Video().render(*m_triangles_cm[i]);
226  for(unsigned int i = 0; i < m_triangles_t.size(); ++i)
227  get_Video().render(*m_triangles_t[i]);
228  }
229 
231  delete m_macrorenderer;
232  m_macrorenderer = macrorenderer;
233  }
234 
235  template <typename VERTEX>
236  struct SORTER {
237  bool operator()(const Triangle<VERTEX> * const lhs, const Triangle<VERTEX> * const rhs) const {
238  return rhs->get_Material() && (!lhs->get_Material() ||
239  *lhs->get_Material() < *rhs->get_Material());
240  }
241  };
242 
244  if(!m_renderer) {
245  Video &vr = get_Video();
246 
247  prerender();
248 
249  vr.lend_pre_uninit(&g_uninit);
250  m_renderer = vr.create_Vertex_Buffer_Renderer(*this);
251  }
252 
253  m_renderer->render();
254  }
255 
257  delete m_renderer;
258  m_renderer = 0;
259  }
260 
261  void Vertex_Buffer::prerender() {
262  if(!m_prerendered) {
263  sort_triangles();
264  set_descriptors();
265  if(m_align_normals)
266  align_similar_normals();
267 
268  m_prerendered = true;
269  }
270  }
271 
272  void Vertex_Buffer::sort_triangles() {
273  std::stable_sort(m_triangles_cm.begin(), m_triangles_cm.end(), SORTER<Vertex3f_Color>());
274  std::stable_sort(m_triangles_t.begin(), m_triangles_t.end(), SORTER<Vertex3f_Texture>());
275  }
276 
277  template <typename VERTEX>
278  struct DESCRIBER {
279  bool operator()(std::vector<Triangle<VERTEX> *> &triangles,
280  std::vector<Vertex_Buffer::Vertex_Buffer_Range *> &descriptors,
281  const size_t &triangles_done) const {
282  const Material mat;
283  size_t last = 0;
284  if(!triangles.empty()) {
285  Material * material_ptr = triangles[0]->get_Material() ?
286  new Material(*triangles[0]->get_Material()) :
287  0;
288  descriptors.push_back(new Vertex_Buffer::Vertex_Buffer_Range(material_ptr, triangles_done, 1u));
289  if(material_ptr)
290  material_ptr->clear_optimization();
291  for(size_t i = 1; i < triangles.size(); ++i) {
292  const Material * material_ptr1 = triangles[i]->get_Material();
293  if(!material_ptr1)
294  material_ptr1 = &mat;
295 
296  if(material_ptr && *material_ptr == *material_ptr1)
297  ++descriptors[last]->num_elements;
298  else {
299  Material * const material_ptr2 = new Material(*material_ptr1);
300  descriptors.push_back(new Vertex_Buffer::Vertex_Buffer_Range(material_ptr2, triangles_done+i, 1u));
301  ++last;
302  material_ptr2->clear_optimization();
303  if(material_ptr) {
304  material_ptr2->optimize_to_follow(*material_ptr);
305  material_ptr->optimize_to_precede(*material_ptr2);
306  }
307  material_ptr = material_ptr2;
308  }
309  }
310  }
311  return triangles.size() != 0u;
312  }
313  };
314 
315  template<typename VERTEX>
316  struct Vertex_Ref {
317  Vertex_Ref() : t(0), which(-1) {}
318  Vertex_Ref(Triangle<VERTEX> * const &t_, const int &which_) : t(t_), which(which_) {}
319 
320  Triangle<VERTEX> *t;
321  int which;
322 
323  struct X_Sorter {
324  bool operator()(const Vertex_Ref<VERTEX> &lhs, const Vertex_Ref<VERTEX> &rhs) const {
325  return lhs.t->get_vertex(lhs.which).position.x <
326  rhs.t->get_vertex(rhs.which).position.x;
327  }
328  };
329 
330  struct Y_Sorter {
331  bool operator()(const Vertex_Ref<VERTEX> &lhs, const Vertex_Ref<VERTEX> &rhs) const {
332  return lhs.t->get_vertex(lhs.which).position.y <
333  rhs.t->get_vertex(rhs.which).position.y;
334  }
335  };
336 
337  struct Z_Sorter {
338  bool operator()(const Vertex_Ref<VERTEX> &lhs, const Vertex_Ref<VERTEX> &rhs) const {
339  return (*lhs.t)[lhs.which].position.z <
340  (*rhs.t)[rhs.which].position.z;
341  }
342  };
343  };
344 
345  template<typename VERTEX>
346  inline void align_similar_normals(const VERTEX v0,
348  const int &which)
349  {
350  const float closeness_threshold_squared = CLOSENESS_THRESHOLD_SQUARED;
351  const float alikeness_threshold = ALIKENESS_THRESHOLD;
352 
353  const VERTEX &v1 = t1[which];
354 
355  if((v0.position - v1.position).magnitude2() < closeness_threshold_squared &&
356  fabs(Vector3f(v0.normal) * Vector3f(v1.normal)) > alikeness_threshold)
357  {
358  VERTEX next(v1);
359  next.normal = v0.normal;
360  t1[which] = next;
361  }
362  }
363 
364  template<typename VERTEX>
365  static void align_similar_normals(std::vector<Triangle<VERTEX> *> &triangles,
366  std::vector<Vertex_Buffer::Vertex_Buffer_Range *> &descriptors)
367  {
368  const float closeness_threshold = CLOSENESS_THRESHOLD;
369 
370  for(std::vector<Vertex_Buffer::Vertex_Buffer_Range *>::iterator it = descriptors.begin();
371  it != descriptors.end();
372  ++it)
373  {
374  std::vector< Vertex_Ref<VERTEX> > verts;
375 
376  verts.reserve(3u * (*it)->num_elements);
377  for(size_t i = (*it)->start, iend = (*it)->start + (*it)->num_elements;
378  i != iend;
379  ++i)
380  {
381  verts.push_back(Vertex_Ref<VERTEX>(triangles[i], 0u));
382  verts.push_back(Vertex_Ref<VERTEX>(triangles[i], 1u));
383  verts.push_back(Vertex_Ref<VERTEX>(triangles[i], 2u));
384  }
385 
386  std::stable_sort(verts.begin(), verts.end(), typename Vertex_Ref<VERTEX>::Z_Sorter());
387 
388  typename std::vector< Vertex_Ref<VERTEX> >::iterator kend = verts.begin();
389 
390  for(typename std::vector< Vertex_Ref<VERTEX> >::iterator jt = verts.begin();
391  jt != verts.end();
392  ++jt)
393  {
394  for(; kend != verts.end(); ++kend)
395  {
396  if((*kend->t)[kend->which].position.z -
397  (*jt->t)[jt->which].position.z > closeness_threshold)
398  {
399  break;
400  }
401  }
402 
403  for(typename std::vector< Vertex_Ref<VERTEX> >::iterator kt = jt + 1;
404  kt != kend;
405  ++kt)
406  {
407  align_similar_normals((*jt->t)[jt->which],
408  *kt->t,
409  kt->which);
410  }
411  }
412  }
413  }
414 
415  void Vertex_Buffer::align_similar_normals() {
416  Zeni::align_similar_normals(m_triangles_cm, m_descriptors_cm);
417  Zeni::align_similar_normals(m_triangles_t, m_descriptors_t);
418  }
419 
420  void Vertex_Buffer::set_descriptors() {
421  DESCRIBER<Vertex3f_Color>()(m_triangles_cm, m_descriptors_cm, 0u);
422  DESCRIBER<Vertex3f_Texture>()(m_triangles_t, m_descriptors_t, 0u);
423  }
424 
426  std::set<Vertex_Buffer *> &vbos = get_vbos();
427 
428  for(std::set<Vertex_Buffer *>::iterator it = vbos.begin();
429  it != vbos.end();
430  ++it)
431  {
432  (*it)->lose();
433  }
434  }
435 
436  std::set<Vertex_Buffer *> & Vertex_Buffer::get_vbos() {
437  static std::set<Vertex_Buffer *> vbos;
438  return vbos;
439  }
440 
441 #ifndef DISABLE_GL_FIXED
442 
443  Vertex_Buffer_Renderer_GL_Fixed::Vertex_Buffer_Renderer_GL_Fixed(Vertex_Buffer &vbo)
445  {
446  memset(m_vbuf, 0, sizeof(VBO_GL) * 6);
447 
448  Video_GL_Fixed &vgl = dynamic_cast<Video_GL_Fixed &>(get_Video());
449 
450  const size_t v_size = vertex_size();
451  const size_t n_size = normal_size();
452  const size_t c_size = color_size();
453  const size_t t_size = texel_size();
454 
455  const size_t vbuf_c_size = v_size * (vbo.num_vertices_cm());
456  const size_t nbuf_c_size = n_size * (vbo.num_vertices_cm());
457  const size_t cbuf_size = c_size * (vbo.num_vertices_cm());
458  const size_t vbuf_t_size = v_size * (vbo.num_vertices_t());
459  const size_t nbuf_t_size = n_size * (vbo.num_vertices_t());
460  const size_t tbuf_size = t_size * (vbo.num_vertices_t());
461 
462  if(vbuf_c_size) {
463  unsigned char *p_verts = new unsigned char [vbuf_c_size];
464  unsigned char *p_normals = new unsigned char [nbuf_c_size];
465  unsigned char *p_colors = new unsigned char [cbuf_size];
466 
467  unsigned char *buffered_verts = p_verts;
468  unsigned char *buffered_normals = p_normals;
469  unsigned char *buffered_colors = p_colors;
470 
471  for(unsigned int i = 0; i < vbo.m_triangles_cm.size(); ++i)
472  for(int j = 0; j < 3; ++j) {
473  memcpy(buffered_verts, (*vbo.m_triangles_cm[i])[j].get_address(), v_size);
474  buffered_verts += v_size;
475 
476  memcpy(buffered_normals, reinterpret_cast<float *>((*vbo.m_triangles_cm[i])[j].get_address())+3, n_size);
477  buffered_normals += n_size;
478 
479  memcpy(buffered_colors, reinterpret_cast<float *>((*vbo.m_triangles_cm[i])[j].get_address())+6, c_size);
480  std::swap(buffered_colors[0], buffered_colors[2]);
481  buffered_colors += c_size;
482  }
483 
484  if(buffers_supported(vgl)) {
485  for(int i = 0; i < 3; ++i)
486  vgl.pglGenBuffersARB(1, &m_vbuf[i].vbo);
487 
488  vgl.pglBindBufferARB(GL_ARRAY_BUFFER_ARB, m_vbuf[0].vbo);
489  vgl.pglBufferDataARB(GL_ARRAY_BUFFER_ARB, int(vbuf_c_size), p_verts, GL_STATIC_DRAW_ARB);
490  vgl.pglBindBufferARB(GL_ARRAY_BUFFER_ARB, m_vbuf[1].vbo);
491  vgl.pglBufferDataARB(GL_ARRAY_BUFFER_ARB, int(nbuf_c_size), p_normals, GL_STATIC_DRAW_ARB);
492  vgl.pglBindBufferARB(GL_ARRAY_BUFFER_ARB, m_vbuf[2].vbo);
493  vgl.pglBufferDataARB(GL_ARRAY_BUFFER_ARB, int(cbuf_size), p_colors, GL_STATIC_DRAW_ARB);
494 
495  delete [] p_verts;
496  delete [] p_normals;
497  delete [] p_colors;
498  }
499  else {
500  m_vbuf[0].alt = p_verts;
501  m_vbuf[1].alt = p_normals;
502  m_vbuf[2].alt = p_colors;
503  }
504  }
505 
506  if(vbuf_t_size) {
507  unsigned char *p_verts = new unsigned char [vbuf_t_size];
508  unsigned char *p_normals = new unsigned char [nbuf_t_size];
509  unsigned char *p_texels = new unsigned char [tbuf_size];
510 
511  unsigned char *buffered_verts = p_verts;
512  unsigned char *buffered_normals = p_normals;
513  unsigned char *buffered_texels = p_texels;
514 
515  for(unsigned int i = 0; i < vbo.m_triangles_t.size(); ++i)
516  for(int j = 0; j < 3; ++j) {
517  memcpy(buffered_verts, (*vbo.m_triangles_t[i])[j].get_address(), v_size);
518  buffered_verts += v_size;
519 
520  memcpy(buffered_normals, reinterpret_cast<float *>((*vbo.m_triangles_t[i])[j].get_address())+3, n_size);
521  buffered_normals += n_size;
522 
523  memcpy(buffered_texels, reinterpret_cast<float *>((*vbo.m_triangles_t[i])[j].get_address())+6, t_size);
524  buffered_texels += t_size;
525  }
526 
527  if(buffers_supported(vgl)) {
528  for(int i = 3; i < 6; ++i)
529  vgl.pglGenBuffersARB(1, &m_vbuf[i].vbo);
530 
531  vgl.pglBindBufferARB(GL_ARRAY_BUFFER_ARB, m_vbuf[3].vbo);
532  vgl.pglBufferDataARB(GL_ARRAY_BUFFER_ARB, int(vbuf_t_size), p_verts, GL_STATIC_DRAW_ARB);
533  vgl.pglBindBufferARB(GL_ARRAY_BUFFER_ARB, m_vbuf[4].vbo);
534  vgl.pglBufferDataARB(GL_ARRAY_BUFFER_ARB, int(nbuf_t_size), p_normals, GL_STATIC_DRAW_ARB);
535  vgl.pglBindBufferARB(GL_ARRAY_BUFFER_ARB, m_vbuf[5].vbo);
536  vgl.pglBufferDataARB(GL_ARRAY_BUFFER_ARB, int(tbuf_size), p_texels, GL_STATIC_DRAW_ARB);
537 
538  delete [] p_verts;
539  delete [] p_normals;
540  delete [] p_texels;
541  }
542  else {
543  m_vbuf[3].alt = p_verts;
544  m_vbuf[4].alt = p_normals;
545  m_vbuf[5].alt = p_texels;
546  }
547  }
548  }
549 
551  Video_GL_Fixed &vgl = dynamic_cast<Video_GL_Fixed &>(get_Video());
552 
553  if(buffers_supported(vgl)) {
554  for(int i = 0; i < 6; ++i)
555  if(m_vbuf[i].vbo)
556  vgl.pglDeleteBuffersARB(1, &m_vbuf[i].vbo);
557  }
558  else {
559  for(int i = 0; i < 6; ++i)
560  delete [] m_vbuf[i].alt;
561  }
562  }
563 
564  class VB_Renderer_GL : public Vertex_Buffer_Microrenderer {
565  public:
566  VB_Renderer_GL(const GLint &first_, const GLsizei &count_)
567  : first(first_),
568  count(count_)
569  {
570  }
571 
572  private:
573  void operator()() const {
575  }
576 
577  GLint first;
578  GLsizei count;
579  };
580 
581  static void render(const Vertex_Buffer_Macrorenderer &macrorenderer, std::vector<Vertex_Buffer::Vertex_Buffer_Range *> &descriptors) {
582  Video &vr = get_Video();
583 
584  for(size_t i = 0u; i < descriptors.size(); ++i) {
585  if(descriptors[i]->material.get())
586  vr.set_Material(*descriptors[i]->material);
587 
588  VB_Renderer_GL microrenderer(int(3u*descriptors[i]->start), int(3u*descriptors[i]->num_elements));
589  macrorenderer(microrenderer);
590 
591  if(descriptors[i]->material.get())
592  vr.unset_Material(*descriptors[i]->material);
593  }
594  }
595 
597  Video_GL_Fixed &vgl = dynamic_cast<Video_GL_Fixed &>(get_Video());
598  const bool buffers_supported_ = buffers_supported(vgl);
599 
602 
603  if(!m_vbo.m_descriptors_cm.empty()) {
604  // Bind Vertex Buffer
605  if(buffers_supported_)
606  vgl.pglBindBufferARB(GL_ARRAY_BUFFER_ARB, m_vbuf[0].vbo);
607  glVertexPointer(3, GL_FLOAT, 0, buffers_supported_ ? 0 : m_vbuf[0].alt);
608  // Bind Normal Buffer
609  if(buffers_supported_)
610  vgl.pglBindBufferARB(GL_ARRAY_BUFFER_ARB, m_vbuf[1].vbo);
611  glNormalPointer(GL_FLOAT, 0, buffers_supported_ ? 0 : m_vbuf[1].alt);
612  // Bind Color Buffer
614  if(buffers_supported_)
615  vgl.pglBindBufferARB(GL_ARRAY_BUFFER_ARB, m_vbuf[2].vbo);
616  glColorPointer(4, GL_UNSIGNED_BYTE, 0, buffers_supported_ ? 0 : m_vbuf[2].alt);
617 
618  Zeni::render(*m_vbo.m_macrorenderer, m_vbo.m_descriptors_cm);
619 
621  }
622 
623  if(!m_vbo.m_descriptors_t.empty()) {
624  // Bind Vertex Buffer
625  if(buffers_supported_)
626  vgl.pglBindBufferARB(GL_ARRAY_BUFFER_ARB, m_vbuf[3].vbo);
627  glVertexPointer(3, GL_FLOAT, 0, buffers_supported_ ? 0 : m_vbuf[3].alt);
628  // Bind Normal Buffer
629  if(buffers_supported_)
630  vgl.pglBindBufferARB(GL_ARRAY_BUFFER_ARB, m_vbuf[4].vbo);
631  glNormalPointer(GL_FLOAT, 0, buffers_supported_ ? 0 : m_vbuf[4].alt);
632  // Bind Texel Buffer
634  if(buffers_supported_)
635  vgl.pglBindBufferARB(GL_ARRAY_BUFFER_ARB, m_vbuf[5].vbo);
636  glTexCoordPointer(2, GL_FLOAT, 0, buffers_supported_ ? 0 : m_vbuf[5].alt);
637 
638  Zeni::render(*m_vbo.m_macrorenderer, m_vbo.m_descriptors_t);
639 
641  }
642 
645  if(buffers_supported_)
647  }
648 
649 #endif
650 #ifndef DISABLE_GL_SHADER
651 
652  Vertex_Buffer_Renderer_GL_Shader::Vertex_Buffer_Renderer_GL_Shader(Vertex_Buffer &vbo)
654  {
655  memset(m_vbuf, 0, sizeof(VBO_GL) * 6);
656 
657  const size_t v_size = vertex_size();
658  const size_t n_size = normal_size();
659  const size_t c_size = color_size();
660  const size_t t_size = texel_size();
661 
662  const size_t vbuf_c_size = v_size * (vbo.num_vertices_cm());
663  const size_t nbuf_c_size = n_size * (vbo.num_vertices_cm());
664  const size_t cbuf_size = c_size * (vbo.num_vertices_cm());
665  const size_t vbuf_t_size = v_size * (vbo.num_vertices_t());
666  const size_t nbuf_t_size = n_size * (vbo.num_vertices_t());
667  const size_t tbuf_size = t_size * (vbo.num_vertices_t());
668 
669  if(vbuf_c_size) {
670  unsigned char *p_verts = new unsigned char [vbuf_c_size];
671  unsigned char *p_normals = new unsigned char [nbuf_c_size];
672  unsigned char *p_colors = new unsigned char [cbuf_size];
673 
674  unsigned char *buffered_verts = p_verts;
675  unsigned char *buffered_normals = p_normals;
676  unsigned char *buffered_colors = p_colors;
677 
678  for(unsigned int i = 0; i < vbo.m_triangles_cm.size(); ++i)
679  for(int j = 0; j < 3; ++j) {
680  memcpy(buffered_verts, (*vbo.m_triangles_cm[i])[j].get_address(), v_size);
681  buffered_verts += v_size;
682 
683  memcpy(buffered_normals, reinterpret_cast<float *>((*vbo.m_triangles_cm[i])[j].get_address())+3, n_size);
684  buffered_normals += n_size;
685 
686  memcpy(buffered_colors, reinterpret_cast<float *>((*vbo.m_triangles_cm[i])[j].get_address())+6, c_size);
687  std::swap(buffered_colors[0], buffered_colors[2]);
688  buffered_colors += c_size;
689  }
690 
691  for(int i = 0; i < 3; ++i)
692  glGenBuffers(1, &m_vbuf[i].vbo);
693 
694  glBindBuffer(GL_ARRAY_BUFFER, m_vbuf[0].vbo);
695  glBufferData(GL_ARRAY_BUFFER, int(vbuf_c_size), p_verts, GL_STATIC_DRAW);
696  glBindBuffer(GL_ARRAY_BUFFER, m_vbuf[1].vbo);
697  glBufferData(GL_ARRAY_BUFFER, int(nbuf_c_size), p_normals, GL_STATIC_DRAW);
698  glBindBuffer(GL_ARRAY_BUFFER, m_vbuf[2].vbo);
699  glBufferData(GL_ARRAY_BUFFER, int(cbuf_size), p_colors, GL_STATIC_DRAW);
700 
701  delete [] p_verts;
702  delete [] p_normals;
703  delete [] p_colors;
704  }
705 
706  if(vbuf_t_size) {
707  unsigned char *p_verts = new unsigned char [vbuf_t_size];
708  unsigned char *p_normals = new unsigned char [nbuf_t_size];
709  unsigned char *p_texels = new unsigned char [tbuf_size];
710 
711  unsigned char *buffered_verts = p_verts;
712  unsigned char *buffered_normals = p_normals;
713  unsigned char *buffered_texels = p_texels;
714 
715  for(unsigned int i = 0; i < vbo.m_triangles_t.size(); ++i)
716  for(int j = 0; j < 3; ++j) {
717  memcpy(buffered_verts, (*vbo.m_triangles_t[i])[j].get_address(), v_size);
718  buffered_verts += v_size;
719 
720  memcpy(buffered_normals, reinterpret_cast<float *>((*vbo.m_triangles_t[i])[j].get_address())+3, n_size);
721  buffered_normals += n_size;
722 
723  memcpy(buffered_texels, reinterpret_cast<float *>((*vbo.m_triangles_t[i])[j].get_address())+6, t_size);
724  buffered_texels += t_size;
725  }
726 
727  for(int i = 3; i < 6; ++i)
728  glGenBuffers(1, &m_vbuf[i].vbo);
729 
730  glBindBuffer(GL_ARRAY_BUFFER, m_vbuf[3].vbo);
731  glBufferData(GL_ARRAY_BUFFER, int(vbuf_t_size), p_verts, GL_STATIC_DRAW);
732  glBindBuffer(GL_ARRAY_BUFFER, m_vbuf[4].vbo);
733  glBufferData(GL_ARRAY_BUFFER, int(nbuf_t_size), p_normals, GL_STATIC_DRAW);
734  glBindBuffer(GL_ARRAY_BUFFER, m_vbuf[5].vbo);
735  glBufferData(GL_ARRAY_BUFFER, int(tbuf_size), p_texels, GL_STATIC_DRAW);
736 
737  delete [] p_verts;
738  delete [] p_normals;
739  delete [] p_texels;
740  }
741  }
742 
744  for(int i = 0; i < 6; ++i)
745  if(m_vbuf[i].vbo)
746  glDeleteBuffers(1, &m_vbuf[i].vbo);
747  }
748 
752 
753  if(!m_vbo.m_descriptors_cm.empty()) {
754  // Bind Vertex Buffer
755  glBindBuffer(GL_ARRAY_BUFFER, m_vbuf[0].vbo);
756  glVertexPointer(3, GL_FLOAT, 0, 0);
757  // Bind Normal Buffer
758  glBindBuffer(GL_ARRAY_BUFFER, m_vbuf[1].vbo);
759  glNormalPointer(GL_FLOAT, 0, 0);
760  // Bind Color Buffer
762  glBindBuffer(GL_ARRAY_BUFFER, m_vbuf[2].vbo);
764 
765  Zeni::render(*m_vbo.m_macrorenderer, m_vbo.m_descriptors_cm);
766 
768  }
769 
770  if(!m_vbo.m_descriptors_t.empty()) {
771  // Bind Vertex Buffer
772  glBindBuffer(GL_ARRAY_BUFFER, m_vbuf[3].vbo);
773  glVertexPointer(3, GL_FLOAT, 0, 0);
774  // Bind Normal Buffer
775  glBindBuffer(GL_ARRAY_BUFFER, m_vbuf[4].vbo);
776  glNormalPointer(GL_FLOAT, 0, 0);
777  // Bind Texel Buffer
779  glBindBuffer(GL_ARRAY_BUFFER, m_vbuf[5].vbo);
780  glTexCoordPointer(2, GL_FLOAT, 0, 0);
781 
782  Zeni::render(*m_vbo.m_macrorenderer, m_vbo.m_descriptors_t);
783 
785  }
786 
790  }
791 
792 #endif
793 #ifndef DISABLE_DX9
794 
795  Vertex_Buffer_Renderer_DX9::Vertex_Buffer_Renderer_DX9(Vertex_Buffer &vbo)
797  {
798  memset(&m_buf_c, 0, sizeof(VBO_DX9));
799  memset(&m_buf_t, 0, sizeof(VBO_DX9));
800 
801  Video_DX9 &vdx = dynamic_cast<Video_DX9 &>(get_Video());
802  size_t vertex_size;
803  char *buffered;
804 
805  if(!vbo.m_triangles_cm.empty()) {
806  const size_t buf_size = vertex_c_size() * vbo.num_vertices_cm();
807 
808 #ifndef DISABLE_VBO
809  if(FAILED
810  (vdx.get_d3d_device()->CreateVertexBuffer(
811  UINT(buf_size),
815  &m_buf_c.data.vbo, NULL)))
816 #endif
817  {
818  m_buf_c.is_vbo = false;
819  m_buf_c.data.alt = new char [buf_size];
820  }
821 #ifndef DISABLE_VBO
822  else
823  m_buf_c.is_vbo = true;
824 #endif
825 
826  vertex_size = vertex_c_size();
827  buffered = 0;
828 
829  if(m_buf_c.is_vbo) {
830  if(FAILED(m_buf_c.data.vbo->Lock(0, 0, reinterpret_cast<void **>(&buffered), 0))) {
831  m_buf_c.data.vbo->Release();
832  throw VBuf_Render_Failure();
833  }
834  }
835  else
836  buffered = m_buf_c.data.alt;
837 
838  for(size_t i = 0u; i != vbo.m_triangles_cm.size(); ++i)
839  for(int j = 0; j != 3; ++j) {
840  memcpy(buffered, (*vbo.m_triangles_cm[i])[j].get_address(), vertex_size);
841  buffered += vertex_size;
842  }
843 
844  if(m_buf_c.is_vbo)
845  m_buf_c.data.vbo->Unlock();
846  }
847 
848  if(!vbo.m_triangles_t.empty()) {
849  const size_t buf_size = vertex_t_size() * vbo.num_vertices_t();
850 
851 #ifndef DISABLE_VBO
852  if(FAILED
853  (vdx.get_d3d_device()->CreateVertexBuffer(
854  UINT(buf_size),
858  &m_buf_t.data.vbo, NULL)))
859 #endif
860  {
861  m_buf_t.is_vbo = false;
862  m_buf_t.data.alt = new char [buf_size];
863  }
864 #ifndef DISABLE_VBO
865  else
866  m_buf_t.is_vbo = true;
867 #endif
868 
869  vertex_size = vertex_t_size();
870  buffered = 0;
871 
872  if(m_buf_t.is_vbo) {
873  if(FAILED(m_buf_t.data.vbo->Lock(0, 0, reinterpret_cast<void **>(&buffered), 0))) {
874  m_buf_t.data.vbo->Release();
875  throw VBuf_Render_Failure();
876  }
877  }
878  else
879  buffered = m_buf_t.data.alt;
880 
881  for(size_t i = 0u; i != vbo.m_triangles_t.size(); ++i)
882  for(int j = 0; j != 3; ++j) {
883  memcpy(buffered, (*vbo.m_triangles_t[i])[j].get_address(), vertex_size);
884  buffered += vertex_size;
885  }
886 
887  if(m_buf_t.is_vbo)
888  m_buf_t.data.vbo->Unlock();
889  }
890  }
891 
893  if(m_buf_c.is_vbo) {
894  if(m_buf_c.data.vbo)
895  m_buf_c.data.vbo->Release();
896  }
897  else
898  delete [] m_buf_c.data.alt;
899 
900  if(m_buf_t.is_vbo) {
901  if(m_buf_t.data.vbo)
902  m_buf_t.data.vbo->Release();
903  }
904  else
905  delete [] m_buf_t.data.alt;
906  }
907 
908  class VB_Renderer_DX9VBO : public Vertex_Buffer_Microrenderer {
909  public:
910  VB_Renderer_DX9VBO(Video_DX9 &vdx, const size_t &StartVertex_, const size_t &PrimitiveCount_)
911  : d3d_device(vdx.get_d3d_device()),
912  StartVertex(StartVertex_),
913  PrimitiveCount(PrimitiveCount_)
914  {
915  }
916 
917  private:
918  void operator()() const {
919  d3d_device->DrawPrimitive(D3DPT_TRIANGLELIST,
920  UINT(StartVertex),
921  UINT(PrimitiveCount));
922  }
923 
924  LPDIRECT3DDEVICE9 d3d_device;
925  size_t StartVertex;
926  size_t PrimitiveCount;
927  };
928 
929  class VB_Renderer_DX9 : public Vertex_Buffer_Microrenderer {
930  public:
931  VB_Renderer_DX9(Video_DX9 &vdx, const size_t &PrimitiveCount_, const void * const &pVertexStreamZeroData_, const size_t &VertexStreamZeroStride_)
932  : d3d_device(vdx.get_d3d_device()),
933  PrimitiveCount(PrimitiveCount_),
934  pVertexStreamZeroData(pVertexStreamZeroData_),
935  VertexStreamZeroStride(VertexStreamZeroStride_)
936  {
937  }
938 
939  private:
940  void operator()() const {
941  d3d_device->DrawPrimitiveUP(D3DPT_TRIANGLELIST,
942  UINT(PrimitiveCount),
943  pVertexStreamZeroData,
944  UINT(VertexStreamZeroStride));
945  }
946 
947  LPDIRECT3DDEVICE9 d3d_device;
948  size_t PrimitiveCount;
949  const void * pVertexStreamZeroData;
950  size_t VertexStreamZeroStride;
951  };
952 
953  static void render(const Vertex_Buffer_Macrorenderer &macrorenderer,
954  std::vector<Vertex_Buffer::Vertex_Buffer_Range *> &descriptors,
956  const unsigned int &stride,
957  Video_DX9 &vdx) {
958 
959  for(unsigned int i = 0; i < descriptors.size(); ++i) {
960  if(descriptors[i]->material.get())
961  vdx.set_Material(*descriptors[i]->material);
962 
963  if(vbo_dx9.is_vbo) {
964  VB_Renderer_DX9VBO microrenderer(vdx, 3u * descriptors[i]->start, descriptors[i]->num_elements);
965  macrorenderer(microrenderer);
966  }
967  else {
968  VB_Renderer_DX9 microrenderer(vdx, descriptors[i]->num_elements, vbo_dx9.data.alt + 3u * descriptors[i]->start, stride);
969  macrorenderer(microrenderer);
970  }
971 
972  if(descriptors[i]->material.get())
973  vdx.unset_Material(*descriptors[i]->material);
974  }
975  }
976 
978  Video_DX9 &vdx = dynamic_cast<Video_DX9 &>(get_Video());
979 
980  vdx.set_fvf(true);
981 
982  if(m_buf_c.data.vbo || m_buf_c.data.alt) {
983  if(m_buf_c.is_vbo)
984  vdx.get_d3d_device()->SetStreamSource(0, m_buf_c.data.vbo, 0, UINT(vertex_c_size()));
985  Zeni::render(*m_vbo.m_macrorenderer, m_vbo.m_descriptors_cm, m_buf_c, UINT(vertex_c_size()), vdx);
986  }
987  if(m_buf_t.data.vbo || m_buf_t.data.alt) {
988  if(m_buf_t.is_vbo)
989  vdx.get_d3d_device()->SetStreamSource(0, m_buf_t.data.vbo, 0, UINT(vertex_t_size()));
990  Zeni::render(*m_vbo.m_macrorenderer, m_vbo.m_descriptors_t, m_buf_t, UINT(vertex_t_size()), vdx);
991  }
992  }
993 
994 #endif
995 
996  Vertex_Buffer::Uninit Vertex_Buffer::g_uninit;
997 
998 }
999 
1000 #include <Zeni/Undefine.h>
#define GL_STATIC_DRAW_ARB
Definition: glew.h:6888
void give_Quadrilateral(Quadrilateral< Vertex2f_Color > *const &quadrilateral)
Give the Vertex_Buffer a Quadrilateral (which it will delete later)
int GLsizei
Definition: gl2.h:29
void debug_render()
Render all Triangles in the Vertex_Buffer individually; Will fail if prerender has been called...
const Material * get_Material() const
Get the Material.
Definition: Renderable.hxx:47
virtual void set_Material(const Material &material)=0
Set a Material.
GLdouble s
Definition: glew.h:1376
GLfloat GLfloat v1
Definition: glew.h:1838
void pglBufferDataARB(const GLenum target, const int size, const GLvoid *const data, const GLenum usage) const
The glBufferDataARB OpenGL function as provided by an extension; Will segfault if has_vertex_buffers(...
The Direct3D9 Rendering System.
Definition: Video_DX9.h:62
#define CLOSENESS_THRESHOLD
Definition: Define.h:121
struct IDirect3DDevice9 * LPDIRECT3DDEVICE9
Definition: d3d9.h:587
LPDIRECT3DDEVICE9 & get_d3d_device()
See DirectX Documentation for details.
Definition: Video_DX9.hxx:48
#define GL_VERTEX_ARRAY
Definition: glew_head.h:723
VERTEX a
Definition: Triangle.h:72
The Video Rendering Singleton.
Definition: Video.h:71
EGLImageKHR EGLint EGLint EGLint * stride
Definition: eglext.h:284
#define NULL
Definition: ftobjs.h:61
An Abstraction of a Vertex in 2-space, colored.
Definition: Vertex2f.h:80
#define D3DUSAGE_WRITEONLY
Definition: d3d9types.h:1609
GLuint start
Definition: glew.h:1239
#define ALIKENESS_THRESHOLD
Definition: Define.h:120
An Abstraction of a Vertex in 3-space, colored.
Definition: Vertex3f.h:76
void lose()
Lose the Vertex_Buffer.
Point3f position
Definition: Vertex2f.h:77
GLdouble GLdouble t
Definition: glew.h:1384
static void render(const Vertex_Buffer_Macrorenderer &macrorenderer, std::vector< Vertex_Buffer::Vertex_Buffer_Range * > &descriptors)
An Abstraction of a Material.
Definition: Material.h:56
int32_t j
Definition: e_log.c:102
#define memset
Definition: SDL_malloc.c:633
#define D3DFVF_TEX1
Definition: d3d9types.h:673
An Abstraction of a Quadrilateral.
Definition: Quadrilateral.h:37
An Abstraction of a Vertex in 3-space, textured.
Definition: Vertex3f.h:113
typedef UINT(WINAPI *PFNWGLGETCONTEXTGPUIDAMDPROC)(HGLRC hglrc)
virtual Vertex_Buffer_Renderer * create_Vertex_Buffer_Renderer(Vertex_Buffer &vertex_buffer)=0
Function for creating a Vertex_Buffer_Renderer.
#define D3DFVF_DIFFUSE
Definition: d3d9types.h:667
Triangle< VERTEX > * get_duplicate() const
Get a duplicate of the Triangle.
Definition: Triangle.hxx:102
void lend_pre_uninit(Event::Handler *const &handler)
Definition: Singleton.hxx:56
#define CLOSENESS_THRESHOLD_SQUARED
Definition: Define.h:119
#define GL_ARRAY_BUFFER
Definition: gl2.h:115
#define GL_COLOR_ARRAY
Definition: glew_head.h:725
Triangle< VERTEX > * get_duplicate_t1() const
Get the second half of the Quadrilateral.
GLuint GLfloat GLfloat GLfloat GLfloat GLfloat GLfloat GLfloat GLfloat GLfloat t1
Definition: glew.h:11582
void set_Material(const Material &material)
Set a Material.
Definition: Video_DX9.cpp:415
Vertex_Buffer_Range(Material *const &m, const size_t &s, const size_t &ne)
GL_APICALL void GL_APIENTRY glBindBuffer(GLenum target, GLuint buffer)
#define D3DFVF_NORMAL
Definition: d3d9types.h:665
A Featureful 3-Space Vector Class.
Definition: Vector3f.h:58
ALuint u
Definition: alMain.h:58
GLint first
Definition: gl2ext.h:1011
#define GL_TRIANGLES
Definition: gl2.h:58
void give_Macrorenderer(Vertex_Buffer_Macrorenderer *const &macrorenderer)
Wraps the final render call.
The OpenGL Rendering System.
virtual void operator()(const Vertex_Buffer_Microrenderer &microrenderer) const
GL_APICALL void GL_APIENTRY glGenBuffers(GLsizei n, GLuint *buffers)
VERTEX c
Definition: Triangle.h:74
virtual void unset_Material(const Material &material)=0
Unset a Material.
virtual void render(const Renderable &renderable)=0
Render a Renderable.
#define GL_STATIC_DRAW
Definition: gl2.h:121
#define glNormalPointer
Definition: gl_mangle.h:1239
GLint GLsizei count
Definition: gl2ext.h:1011
void pglDeleteBuffersARB(const GLsizei n, GLuint *const buffers) const
The glDeleteBuffersARB OpenGL function as provided by an extension; Will segfault if has_vertex_buffe...
void align_similar_normals(const VERTEX v0, Triangle< VERTEX > &t1, const int &which)
void pglGenBuffersARB(const GLsizei n, GLuint *const buffers) const
The glGenBuffersARB OpenGL function as provided by an extension; Will segfault if has_vertex_buffers(...
GLfloat v0
Definition: glew.h:1834
void fax_Quadrilateral(const Quadrilateral< Vertex2f_Color > *const &quadrilateral)
Give the Vertex_Buffer a copy of a Quadrilateral.
#define GL_TEXTURE_COORD_ARRAY
Definition: glew_head.h:727
static void lose_all()
void unset_Material(const Material &material)
Unset a Material.
Definition: Video_DX9.cpp:419
union Zeni::Vertex_Buffer_Renderer_DX9::VBO_DX9::VBO_DX9_impl data
#define glDisableClientState
Definition: gl_mangle.h:390
A Vertex_Buffer that accepts Triangle and Quadrilaterals.
Definition: Vertex_Buffer.h:85
void give_Triangle(Triangle< Vertex2f_Color > *const &triangle)
Give the Vertex_Buffer a Triangle (which it will delete later)
#define glTexCoordPointer
Definition: gl_mangle.h:1739
VERTEX b
Definition: Triangle.h:73
#define glColorPointer
Definition: gl_mangle.h:236
void fax_Triangle(const Triangle< Vertex2f_Color > *const &triangle)
Give the Vertex_Buffer a copy of a Triangle.
int GLint
Definition: gl2.h:28
An Abstraction of a Vertex in 2-space, textured.
Definition: Vertex2f.h:115
Triangle< VERTEX > * get_duplicate_t0() const
Get the first half of the Quadrilateral.
void fax_Material(const Material *const &material)
Set the Material, giving the Renderable a copy.
Definition: Renderable.cpp:50
void swap(Zeni::String &lhs, Zeni::String &rhs)
Definition: String.cpp:578
#define memcpy
Definition: SDL_malloc.c:634
#define glEnableClientState
Definition: gl_mangle.h:438
#define GL_NORMAL_ARRAY
Definition: glew_head.h:724
#define GL_UNSIGNED_BYTE
Definition: gl2.h:236
struct Zeni::Vertex_Buffer_Renderer_DX9::VBO_DX9 m_buf_t
#define D3DFVF_XYZ
Definition: d3d9types.h:656
void render()
Render the Vertex_Buffer.
An Abstraction of a Triangle.
Definition: Triangle.h:36
static void clear_triangles(std::vector< Triangle< VERTEX > * > &triangles, std::vector< Vertex_Buffer::Vertex_Buffer_Range * > &descriptors)
#define GL_FLOAT
Definition: gl2.h:241
Video & get_Video()
Get access to the singleton.
Definition: Video.cpp:149
#define glVertexPointer
Definition: gl_mangle.h:2196
int i
Definition: pngrutil.c:1377
void set_fvf(const bool &is_3d)
Definition: Video_DX9.cpp:808
GL_APICALL void GL_APIENTRY glDeleteBuffers(GLsizei n, const GLuint *buffers)
GL_APICALL void GL_APIENTRY glBufferData(GLenum target, GLsizeiptr size, const GLvoid *data, GLenum usage)
#define glDrawArrays
Definition: gl_mangle.h:403
const Uint32 & get_Color() const
Get the current Color.
Definition: Vertex2f.hxx:39
struct Zeni::Vertex_Buffer_Renderer_DX9::VBO_DX9 m_buf_c
Point2f texture_coordinate
Definition: Vertex2f.h:144
double fabs(double x)
Definition: s_fabs.c:29
#define GL_ARRAY_BUFFER_ARB
Definition: glew.h:6865
void pglBindBufferARB(const GLenum target, const GLuint buffer) const
The glBindBufferARB OpenGL function as provided by an extension; Will segfault if has_vertex_buffers(...
#define false
Definition: ftrandom.c:50
GLfloat GLfloat GLfloat v2
Definition: glew.h:1842
const GLdouble * m
Definition: glew.h:8385