]> git.tdb.fi Git - libs/gl.git/blob - source/mesh.cpp
Add a rendering supervisor class
[libs/gl.git] / source / mesh.cpp
1 /* $Id$
2
3 This file is part of libmspgl
4 Copyright © 2007-2011  Mikko Rasa, Mikkosoft Productions
5 Distributed under the LGPL
6 */
7
8 #include "buffer.h"
9 #include "extension.h"
10 #include "mesh.h"
11 #include "renderer.h"
12
13 using namespace std;
14
15 namespace Msp {
16 namespace GL {
17
18 Mesh::Mesh():
19         vertices(VERTEX3),
20         ibuf(0),
21         defer_ibuf(true)
22 { }
23
24 Mesh::Mesh(const VertexFormat &f):
25         vertices(f),
26         ibuf(0),
27         defer_ibuf(true)
28 { }
29
30 Mesh::~Mesh()
31 {
32         delete ibuf;
33 }
34
35 void Mesh::clear()
36 {
37         vertices.clear();
38         batches.clear();
39 }
40
41 void Mesh::use_buffers(bool b)
42 {
43         if(b)
44         {
45                 vertices.use_vertex_buffer();
46                 if(!ibuf)
47                         ibuf = new Buffer(ELEMENT_ARRAY_BUFFER);
48                 defer_ibuf = false;
49         }
50         else
51         {
52                 vertices.use_vertex_buffer(0);
53                 delete ibuf;
54                 ibuf = 0;
55                 defer_ibuf = false;
56         }
57 }
58
59 unsigned Mesh::get_n_vertices() const
60 {
61         return vertices.size();
62 }
63
64 float *Mesh::modify_vertex(unsigned i)
65 {
66         return vertices.modify(i);
67 }
68
69 void Mesh::add_batch(const Batch &b)
70 {
71         bool can_append = false;
72         if(!batches.empty())
73         {
74                 PrimitiveType type = b.get_type();
75                 can_append = (type==batches.back().get_type() &&
76                         type!=LINE_STRIP && type!=LINE_LOOP && type!=POLYGON &&
77                         (type!=TRIANGLE_FAN || is_supported("GL_NV_primitive_restart")));
78         }
79
80         if(defer_ibuf)
81         {
82                 ibuf = new Buffer(ELEMENT_ARRAY_BUFFER);
83                 defer_ibuf = false;
84         }
85
86         if(can_append)
87                 batches.back().append(b);
88         else
89         {
90                 Batch *prev = (batches.empty() ? 0 : &batches.back());
91                 batches.push_back(b);
92                 if(ibuf)
93                         batches.back().use_index_buffer(ibuf, prev);
94         }
95 }
96
97 void Mesh::draw() const
98 {
99         vertices.apply();
100
101         if(ibuf)
102                 ibuf->bind_to(ELEMENT_ARRAY_BUFFER);
103
104         for(list<Batch>::const_iterator i=batches.begin(); i!=batches.end(); ++i)
105                 i->draw();
106
107         if(ibuf)
108                 Buffer::unbind_from(ELEMENT_ARRAY_BUFFER);
109 }
110
111 void Mesh::draw(Renderer &renderer) const
112 {
113         renderer.set_vertex_array(&vertices);
114         renderer.set_element_buffer(ibuf);
115
116         for(list<Batch>::const_iterator i=batches.begin(); i!=batches.end(); ++i)
117                 renderer.draw(*i);
118 }
119
120
121 Mesh::Loader::Loader(Mesh &m):
122         DataFile::ObjectLoader<Mesh>(m)
123 {
124         add("vertices", &Loader::vertices);
125         add("batch",    &Loader::batch);
126 }
127
128 void Mesh::Loader::vertices(VertexFormat f)
129 {
130         obj.vertices.reset(f);
131         load_sub(obj.vertices);
132 }
133
134 void Mesh::Loader::batch(PrimitiveType p)
135 {
136         Batch btc(p);
137         load_sub(btc);
138         obj.add_batch(btc);
139 }
140
141 } // namespace GL
142 } // namespace Msp