20 #if !defined(_MSC_VER)
28 #include "signals/signal.h"
29 #include "generic/managed.h"
30 #include "generic/uniquely_identifiable.h"
31 #include "generic/notifies_destruction.h"
40 enum VertexAttributeType {
41 VERTEX_ATTRIBUTE_TYPE_EMPTY = 0,
42 VERTEX_ATTRIBUTE_TYPE_POSITION,
43 VERTEX_ATTRIBUTE_TYPE_NORMAL,
44 VERTEX_ATTRIBUTE_TYPE_TEXCOORD0,
45 VERTEX_ATTRIBUTE_TYPE_TEXCOORD1,
46 VERTEX_ATTRIBUTE_TYPE_TEXCOORD2,
47 VERTEX_ATTRIBUTE_TYPE_TEXCOORD3,
48 VERTEX_ATTRIBUTE_TYPE_TEXCOORD4,
49 VERTEX_ATTRIBUTE_TYPE_TEXCOORD5,
50 VERTEX_ATTRIBUTE_TYPE_TEXCOORD6,
51 VERTEX_ATTRIBUTE_TYPE_TEXCOORD7,
52 VERTEX_ATTRIBUTE_TYPE_DIFFUSE,
53 VERTEX_ATTRIBUTE_TYPE_SPECULAR
56 VertexAttribute attribute_for_type(VertexAttributeType type,
const VertexSpecification& spec);
63 typedef std::shared_ptr<VertexData> ptr;
76 void clear(
bool release_memory=
false);
79 bool move_by(int32_t amount);
80 bool move_to(int32_t index);
85 uint64_t last_updated()
const;
87 void position(
float x,
float y,
float z,
float w);
88 void position(
float x,
float y,
float z);
89 void position(
float x,
float y);
90 void position(
const Vec3& pos);
91 void position(
const Vec2& pos);
92 void position(
const Vec4& pos);
95 const T* position_at(uint32_t idx)
const;
98 const T* normal_at(uint32_t idx)
const;
101 const T* texcoord0_at(uint32_t idx)
const;
104 const T* texcoord1_at(uint32_t idx)
const;
107 const T* diffuse_at(
const uint32_t index)
const;
115 Vec4 position_nd_at(uint32_t idx,
float defz=0.0f,
float defw=1.0f)
const;
117 void normal(
float x,
float y,
float z);
118 void normal(
const Vec3& n);
120 void tex_coord0(
float u,
float v);
121 void tex_coord0(
float u,
float v,
float w);
122 void tex_coord0(
float x,
float y,
float z,
float w);
123 void tex_coord0(
const Vec2& vec) { tex_coord0(vec.x, vec.y); }
125 void tex_coord1(
float u,
float v);
126 void tex_coord1(
float u,
float v,
float w);
127 void tex_coord1(
float x,
float y,
float z,
float w);
128 void tex_coord1(
const Vec2& vec) { tex_coord1(vec.x, vec.y); }
130 void tex_coord2(
float u,
float v);
131 void tex_coord2(
float u,
float v,
float w);
132 void tex_coord2(
float x,
float y,
float z,
float w);
133 void tex_coord2(
const Vec2& vec) { tex_coord2(vec.x, vec.y); }
135 void tex_coord3(
float u,
float v);
136 void tex_coord3(
float u,
float v,
float w);
137 void tex_coord3(
float x,
float y,
float z,
float w);
138 void tex_coord3(
const Vec2& vec) { tex_coord3(vec.x, vec.y); }
140 void diffuse(
float r,
float g,
float b);
141 void diffuse(
float r,
float g,
float b,
float a);
142 void diffuse(uint8_t r, uint8_t g, uint8_t b, uint8_t a);
143 void diffuse(
const Color& color);
145 void specular(
float r,
float g,
float b,
float a);
146 void specular(
const Color& color);
148 uint32_t count()
const {
return vertex_count_; }
150 sig::signal<void ()>& signal_update_complete() {
return signal_update_complete_; }
151 bool empty()
const {
return data_.empty(); }
153 int32_t cursor_position()
const {
return cursor_position_; }
154 int32_t cursor_offset()
const {
return cursor_position_ * stride_; }
156 inline uint32_t stride()
const {
160 uint32_t copy_vertex_to_another(
VertexData& out, uint32_t idx) {
161 if(out.vertex_specification_ != this->vertex_specification_) {
162 throw std::runtime_error(
"Cannot copy vertex as formats differ");
165 uint32_t start = idx * stride();
166 uint32_t end = (idx + 1) * stride();
168 out.data_.insert(out.data_.end(), data_.begin() + start, data_.begin() + end);
172 return out.count() - 1;
176 if(vertex_specification_ != other.vertex_specification_) {
177 S_ERROR(
"Tried to extend vertex data with incompatible data");
181 data_.insert(data_.end(), other.data_.begin(), other.data_.end());
182 vertex_count_ += other.count();
186 void transform_by(
const Mat4& transform) {
187 for(
auto i = 0u; i < count(); ++i) {
190 Vec4 pos = position_nd_at(i);
191 pos = transform * pos;
192 if(vertex_specification_.position_attribute == VERTEX_ATTRIBUTE_2F) {
193 position(pos.x, pos.y);
194 }
else if(vertex_specification_.position_attribute == VERTEX_ATTRIBUTE_3F) {
195 position(pos.x, pos.y, pos.z);
196 }
else if(vertex_specification_.position_attribute == VERTEX_ATTRIBUTE_4F) {
199 S_ERROR(
"Attempted to transform unsupported position attribute type");
204 bool interp_vertex(uint32_t source_idx,
const VertexData& dest_state, uint32_t dest_idx,
VertexData& out, uint32_t out_idx,
float interp);
205 uint8_t* data() {
if(empty()) {
return nullptr; }
return &data_[0]; }
206 const uint8_t* data()
const {
if(empty()) {
return nullptr; }
return &data_[0]; }
207 std::size_t data_size()
const {
return data_.size(); }
209 VertexAttribute attribute_for_type(VertexAttributeType type)
const;
211 void reserve(uint32_t size);
213 void resize(uint32_t size);
229 std::vector<uint8_t> data_;
230 uint32_t vertex_count_ = 0;
231 uint32_t stride_ = 0;
232 int32_t cursor_position_ = 0;
233 uint64_t last_updated_ = 0;
235 void tex_coordX(uint8_t which,
float u);
236 void tex_coordX(uint8_t which,
float u,
float v);
237 void tex_coordX(uint8_t which,
float u,
float v,
float w);
238 void tex_coordX(uint8_t which,
float x,
float y,
float z,
float w);
239 void check_texcoord(uint8_t which);
241 VertexAttribute attribute_from_type(VertexAttributeType type);
247 void position_checks();
248 void recalc_attributes();
250 friend class VertexDataTest;
253 typedef std::shared_ptr<VertexData> VertexDataPtr;
256 const Vec2* VertexData::position_at<Vec2>(uint32_t idx)
const;
259 const Vec3* VertexData::position_at<Vec3>(uint32_t idx)
const;
262 const Vec4* VertexData::position_at<Vec4>(uint32_t idx)
const;
265 const Vec2* VertexData::normal_at<Vec2>(uint32_t idx)
const;
268 const Vec3* VertexData::normal_at<Vec3>(uint32_t idx)
const;
271 const Vec2* VertexData::texcoord0_at<Vec2>(uint32_t idx)
const;
274 const Vec3* VertexData::texcoord0_at<Vec3>(uint32_t idx)
const;
277 const Vec4* VertexData::texcoord0_at<Vec4>(uint32_t idx)
const;
280 const Vec2* VertexData::texcoord1_at<Vec2>(uint32_t idx)
const;
283 const Vec3* VertexData::texcoord1_at<Vec3>(uint32_t idx)
const;
286 const Vec4* VertexData::texcoord1_at<Vec4>(uint32_t idx)
const;
289 const Color* VertexData::diffuse_at(
const uint32_t index)
const;
292 const uint8_t* VertexData::diffuse_at(
const uint32_t index)
const;
294 typedef uint32_t Index;
311 return ptr_ == rhs.ptr_;
315 return ptr_ != rhs.ptr_;
318 uint32_t operator*()
const {
320 case INDEX_TYPE_8_BIT:
321 return *((uint8_t*) ptr_);
322 case INDEX_TYPE_16_BIT:
323 return *((uint16_t*) ptr_);
324 case INDEX_TYPE_32_BIT:
326 return *((uint32_t*) ptr_);
343 typedef std::shared_ptr<IndexData> ptr;
356 void clear(
bool release_memory=
false);
357 void resize(uint32_t size);
358 void reserve(uint32_t size) { indices_.reserve(size * stride()); }
360 std::vector<uint32_t> all();
362 uint32_t min_index()
const {
return min_index_; }
363 uint32_t max_index()
const {
return max_index_; }
365 template<
typename T,
int BS>
366 void _index(uint32_t* indexes, std::size_t count) {
367 auto i = indices_.size();
368 indices_.resize(i + (count * BS));
370 uint32_t* idx = indexes;
371 for(std::size_t j = 0; j < count; ++j) {
372 min_index_ = std::min(min_index_, *idx);
373 max_index_ = std::max(max_index_, *idx);
375 auto ptr = (T*) &indices_[i];
382 void index(uint32_t* indexes, std::size_t count) {
383 switch(index_type_) {
384 case INDEX_TYPE_8_BIT:
385 _index<uint8_t, 1>(indexes, count);
387 case INDEX_TYPE_16_BIT:
388 _index<uint16_t, 2>(indexes, count);
390 case INDEX_TYPE_32_BIT:
391 _index<uint32_t, 4>(indexes, count);
397 count_ = (uint32_t)(indices_.size() / stride_);
400 void index(uint32_t idx) {
405 uint64_t last_updated()
const;
407 uint32_t at(
const uint32_t i)
const {
408 auto ptr = &indices_[i * stride()];
410 switch(index_type_) {
411 case INDEX_TYPE_8_BIT:
return *ptr;
412 case INDEX_TYPE_16_BIT:
return *((uint16_t*) ptr);
413 case INDEX_TYPE_32_BIT:
return *((uint32_t*) ptr);
415 throw std::logic_error(
"Invalid index type");
419 uint32_t count()
const {
423 bool operator==(
const IndexData& other)
const {
424 return this->indices_ == other.indices_;
427 bool operator!=(
const IndexData& other)
const {
428 return !(*
this == other);
431 sig::signal<void ()>& signal_update_complete() {
return signal_update_complete_; }
433 const uint8_t* data()
const {
return &indices_[0]; }
434 std::size_t data_size()
const {
return indices_.size() *
sizeof(uint8_t); }
436 uint32_t stride()
const {
440 IndexType index_type()
const {
return index_type_; }
443 IndexType index_type_;
444 std::vector<uint8_t> indices_;
445 uint32_t stride_ = 0;
447 uint64_t last_updated_ = 0;
452 uint32_t min_index_ = ~0;
453 uint32_t max_index_ = 0;
456 typedef IndexData::ptr IndexDataPtr;