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