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