24 #include "signals/signal.h"
25 #include "generic/managed.h"
26 #include "generic/uniquely_identifiable.h"
27 #include "generic/notifies_destruction.h"
36 enum VertexAttributeType {
37 VERTEX_ATTRIBUTE_TYPE_EMPTY = 0,
38 VERTEX_ATTRIBUTE_TYPE_POSITION,
39 VERTEX_ATTRIBUTE_TYPE_NORMAL,
40 VERTEX_ATTRIBUTE_TYPE_TEXCOORD0,
41 VERTEX_ATTRIBUTE_TYPE_TEXCOORD1,
42 VERTEX_ATTRIBUTE_TYPE_TEXCOORD2,
43 VERTEX_ATTRIBUTE_TYPE_TEXCOORD3,
44 VERTEX_ATTRIBUTE_TYPE_TEXCOORD4,
45 VERTEX_ATTRIBUTE_TYPE_TEXCOORD5,
46 VERTEX_ATTRIBUTE_TYPE_TEXCOORD6,
47 VERTEX_ATTRIBUTE_TYPE_TEXCOORD7,
48 VERTEX_ATTRIBUTE_TYPE_DIFFUSE,
49 VERTEX_ATTRIBUTE_TYPE_SPECULAR
52 VertexAttribute attribute_for_type(VertexAttributeType type,
const VertexSpecification& spec);
71 void clear(
bool release_memory=
false);
74 bool move_by(int32_t amount);
75 bool move_to(int32_t index);
80 uint64_t last_updated()
const;
82 void position(
float x,
float y,
float z,
float w);
83 void position(
float x,
float y,
float z);
84 void position(
float x,
float y);
85 void position(
const Vec3& pos);
86 void position(
const Vec2& pos);
87 void position(
const Vec4& pos);
90 const T* position_at(uint32_t idx)
const;
93 const T* normal_at(uint32_t idx)
const;
96 const T* texcoord0_at(uint32_t idx)
const;
99 const T* texcoord1_at(uint32_t idx)
const;
102 const T* diffuse_at(
const uint32_t index)
const;
110 Vec4 position_nd_at(uint32_t idx,
float defz=0.0f,
float defw=1.0f)
const;
112 void normal(
float x,
float y,
float z);
113 void normal(
const Vec3& n);
115 void tex_coord0(
float u,
float v);
116 void tex_coord0(
float u,
float v,
float w);
117 void tex_coord0(
float x,
float y,
float z,
float w);
118 void tex_coord0(
const Vec2& vec) { tex_coord0(vec.x, vec.y); }
120 void tex_coord1(
float u,
float v);
121 void tex_coord1(
float u,
float v,
float w);
122 void tex_coord1(
float x,
float y,
float z,
float w);
123 void tex_coord1(
const Vec2& vec) { tex_coord1(vec.x, vec.y); }
125 void tex_coord2(
float u,
float v);
126 void tex_coord2(
float u,
float v,
float w);
127 void tex_coord2(
float x,
float y,
float z,
float w);
128 void tex_coord2(
const Vec2& vec) { tex_coord2(vec.x, vec.y); }
130 void tex_coord3(
float u,
float v);
131 void tex_coord3(
float u,
float v,
float w);
132 void tex_coord3(
float x,
float y,
float z,
float w);
133 void tex_coord3(
const Vec2& vec) { tex_coord3(vec.x, vec.y); }
135 void diffuse(
float r,
float g,
float b,
float a);
136 void diffuse(uint8_t r, uint8_t g, uint8_t b, uint8_t a);
137 void diffuse(
const Colour& colour);
139 void specular(
float r,
float g,
float b,
float a);
140 void specular(
const Colour& colour);
142 uint32_t count()
const {
return vertex_count_; }
144 sig::signal<void ()>& signal_update_complete() {
return signal_update_complete_; }
145 bool empty()
const {
return data_.empty(); }
147 int32_t cursor_position()
const {
return cursor_position_; }
148 int32_t cursor_offset()
const {
return cursor_position_ * stride_; }
150 inline uint32_t stride()
const {
154 uint32_t copy_vertex_to_another(
VertexData& out, uint32_t idx) {
155 if(out.vertex_specification_ != this->vertex_specification_) {
156 throw std::runtime_error(
"Cannot copy vertex as formats differ");
159 uint32_t start = idx * stride();
160 uint32_t end = (idx + 1) * stride();
162 out.data_.insert(out.data_.end(), data_.begin() + start, data_.begin() + end);
166 return out.count() - 1;
170 if(vertex_specification_ != other.vertex_specification_) {
171 S_ERROR(
"Tried to extend vertex data with incompatible data");
175 data_.insert(data_.end(), other.data_.begin(), other.data_.end());
176 vertex_count_ += other.count();
180 void transform_by(
const Mat4& transform) {
181 for(
auto i = 0u; i < count(); ++i) {
184 Vec4 pos = position_nd_at(i);
185 pos = transform * pos;
186 if(vertex_specification_.position_attribute == VERTEX_ATTRIBUTE_2F) {
187 position(pos.x, pos.y);
188 }
else if(vertex_specification_.position_attribute == VERTEX_ATTRIBUTE_3F) {
189 position(pos.x, pos.y, pos.z);
190 }
else if(vertex_specification_.position_attribute == VERTEX_ATTRIBUTE_4F) {
193 S_ERROR(
"Attempted to transform unsupported position attribute type");
198 bool interp_vertex(uint32_t source_idx,
const VertexData& dest_state, uint32_t dest_idx,
VertexData& out, uint32_t out_idx,
float interp);
199 uint8_t* data() {
if(empty()) {
return nullptr; }
return &data_[0]; }
200 const uint8_t* data()
const {
if(empty()) {
return nullptr; }
return &data_[0]; }
201 uint32_t data_size()
const {
return data_.size(); }
203 VertexAttribute attribute_for_type(VertexAttributeType type)
const;
205 void reserve(uint32_t size);
207 void resize(uint32_t size);
223 std::vector<uint8_t> data_;
224 uint32_t vertex_count_ = 0;
225 uint32_t stride_ = 0;
226 int32_t cursor_position_ = 0;
227 uint64_t last_updated_ = 0;
229 void tex_coordX(uint8_t which,
float u);
230 void tex_coordX(uint8_t which,
float u,
float v);
231 void tex_coordX(uint8_t which,
float u,
float v,
float w);
232 void tex_coordX(uint8_t which,
float x,
float y,
float z,
float w);
233 void check_texcoord(uint8_t which);
235 VertexAttribute attribute_from_type(VertexAttributeType type);
241 void position_checks();
242 void recalc_attributes();
244 friend class VertexDataTest;
247 typedef std::shared_ptr<VertexData> VertexDataPtr;
250 const Vec2* VertexData::position_at<Vec2>(uint32_t idx)
const;
253 const Vec3* VertexData::position_at<Vec3>(uint32_t idx)
const;
256 const Vec4* VertexData::position_at<Vec4>(uint32_t idx)
const;
259 const Vec2* VertexData::normal_at<Vec2>(uint32_t idx)
const;
262 const Vec3* VertexData::normal_at<Vec3>(uint32_t idx)
const;
265 const Vec2* VertexData::texcoord0_at<Vec2>(uint32_t idx)
const;
268 const Vec3* VertexData::texcoord0_at<Vec3>(uint32_t idx)
const;
271 const Vec4* VertexData::texcoord0_at<Vec4>(uint32_t idx)
const;
274 const Vec2* VertexData::texcoord1_at<Vec2>(uint32_t idx)
const;
277 const Vec3* VertexData::texcoord1_at<Vec3>(uint32_t idx)
const;
280 const Vec4* VertexData::texcoord1_at<Vec4>(uint32_t idx)
const;
283 const Colour* VertexData::diffuse_at(
const uint32_t index)
const;
286 const uint8_t* VertexData::diffuse_at(
const uint32_t index)
const;
288 typedef uint32_t Index;
305 return ptr_ == rhs.ptr_;
309 return ptr_ != rhs.ptr_;
312 uint32_t operator*()
const {
314 case INDEX_TYPE_8_BIT:
315 return *((uint8_t*) ptr_);
316 case INDEX_TYPE_16_BIT:
317 return *((uint16_t*) ptr_);
318 case INDEX_TYPE_32_BIT:
320 return *((uint32_t*) ptr_);
349 void clear(
bool release_memory=
false);
350 void resize(uint32_t size);
351 void reserve(uint32_t size) { indices_.reserve(size * stride()); }
353 std::vector<uint32_t> all();
355 uint32_t min_index()
const {
return min_index_; }
356 uint32_t max_index()
const {
return max_index_; }
358 template<
typename T,
int BS>
359 void _index(uint32_t* indexes, std::size_t count) {
360 auto i = indices_.size();
361 indices_.resize(i + (count * BS));
363 uint32_t* idx = indexes;
364 for(std::size_t j = 0; j < count; ++j) {
365 min_index_ = std::min(min_index_, *idx);
366 max_index_ = std::max(max_index_, *idx);
368 auto ptr = (T*) &indices_[i];
375 void index(uint32_t* indexes, std::size_t count) {
376 switch(index_type_) {
377 case INDEX_TYPE_8_BIT:
378 _index<uint8_t, 1>(indexes, count);
380 case INDEX_TYPE_16_BIT:
381 _index<uint16_t, 2>(indexes, count);
383 case INDEX_TYPE_32_BIT:
384 _index<uint32_t, 4>(indexes, count);
390 count_ = indices_.size() / stride_;
393 void index(uint32_t idx) {
398 uint64_t last_updated()
const;
400 uint32_t at(
const uint32_t i)
const {
401 auto ptr = &indices_[i * stride()];
403 switch(index_type_) {
404 case INDEX_TYPE_8_BIT:
return *ptr;
405 case INDEX_TYPE_16_BIT:
return *((uint16_t*) ptr);
406 case INDEX_TYPE_32_BIT:
return *((uint32_t*) ptr);
408 throw std::logic_error(
"Invalid index type");
412 uint32_t count()
const {
416 bool operator==(
const IndexData& other)
const {
417 return this->indices_ == other.indices_;
420 bool operator!=(
const IndexData& other)
const {
421 return !(*
this == other);
424 sig::signal<void ()>& signal_update_complete() {
return signal_update_complete_; }
426 const uint8_t* data()
const {
return &indices_[0]; }
427 std::size_t data_size()
const {
return indices_.size() *
sizeof(uint8_t); }
429 uint32_t stride()
const {
433 IndexType index_type()
const {
return index_type_; }
436 IndexType index_type_;
437 std::vector<uint8_t> indices_;
438 uint32_t stride_ = 0;
440 uint64_t last_updated_ = 0;
445 uint32_t min_index_ = ~0;
446 uint32_t max_index_ = 0;
449 typedef std::shared_ptr<IndexData> IndexDataPtr;