summaryrefslogtreecommitdiffstats
path: root/o3d/core/cross/skin.h
blob: 70193db0a70a754e444daf44e689796a5245db66 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
/*
 * Copyright 2009, Google Inc.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are
 * met:
 *
 *     * Redistributions of source code must retain the above copyright
 * notice, this list of conditions and the following disclaimer.
 *     * Redistributions in binary form must reproduce the above
 * copyright notice, this list of conditions and the following disclaimer
 * in the documentation and/or other materials provided with the
 * distribution.
 *     * Neither the name of Google Inc. nor the names of its
 * contributors may be used to endorse or promote products derived from
 * this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */


// This file contains the declaration of class Skin.

#ifndef O3D_CORE_CROSS_SKIN_H_
#define O3D_CORE_CROSS_SKIN_H_

#include <vector>
#include "core/cross/buffer.h"
#include "core/cross/param_object.h"
#include "core/cross/vertex_source.h"
#include "core/cross/param_array.h"

namespace o3d {

class MemoryReadStream;
class RawData;

// A Skin holds an array of matrix indices and influences for vertices in a skin
// as well as the inverse bind pose matrices for each bone.
class Skin : public NamedObject {
 public:
  typedef SmartPointer<Skin> Ref;
  typedef WeakPointer<Skin> WeakPointerType;

  // A four-character identifier used in the binary serialization format
  // (not exposed to Javascript)
  static const char *kSerializationID;

  // One matrix-weight pair.
  struct Influence {
    Influence()
        : matrix_index(0),
          weight(0) {
    }
    Influence(unsigned index, float weight)
        : matrix_index(index),
          weight(weight) {
    }
    unsigned matrix_index;
    float weight;
  };

  typedef std::vector<Influence> Influences;
  typedef std::vector<Influences> InfluencesArray;

  typedef std::vector<Matrix4> MatrixArray;

  const InfluencesArray& influences() const {
    return influences_array_;
  }

  // Sets the data for an individual vertex.
  // Parameters:
  //   vertex_index: Index of vertex to set.
  //   influences: The matrix-weight pairs.
  void SetVertexInfluences(unsigned vertex_index,
                           const Influences& influences);

  // Gets the data for an individual vertex.
  // Parameters:
  //   vertex_index: Index of vertex to set.
  // Returns:
  //   The influence data for the requested vertex or NULL if the index is out
  //   of range.
  const Influences* GetVertexInfluences(unsigned vertex_index) const;

  // Gets the highest matrix index referenced by the influences.
  // Returns:
  //   The highest matrix index referenced by the influences.
  unsigned GetHighestMatrixIndex() const;

  // Gets the highest number of influences on any vertex.
  // Returns:
  //   The highest number of influences on any vertex.
  unsigned GetHighestInfluences() const;

  // Sets the inverse bind pose matrix for a particular joint/bone/transform.
  // Parameters:
  //   index: index of bone/joint/transform
  //   matrix: Inverse bind pose matrix for that joint.
  void SetInverseBindPoseMatrix(unsigned index, const Matrix4& matrix);

  // Gets the vector of inverse bind pose matrices.
  // Returns:
  //   the vector of inverse bind pose matrices.
  const MatrixArray& inverse_bind_pose_matrices() const {
    return inverse_bind_pose_matrices_;
  }

  // Sete the vector of inverse bind pose matrices.
  void set_inverse_bind_pose_matrices(const MatrixArray& matrices) {
    inverse_bind_pose_matrices_ = matrices;
  }

  // Gets a weak pointer to us.
  WeakPointerType GetWeakPointer() const {
    return weak_pointer_manager_.GetWeakPointer();
  }

  // De-serializes the data contained in |raw_data|
  // The entire contents of |raw_data| from start to finish will
  // be used
  bool Set(o3d::RawData *raw_data);

  // De-serializes the data contained in |raw_data|
  // starting at byte offset |offset| and using |length|
  // bytes
  bool Set(o3d::RawData *raw_data,
           size_t offset,
           size_t length);

  // De-serializes a skin from its persistent binary representation
  bool LoadFromBinaryData(MemoryReadStream *stream);

 private:
  explicit Skin(ServiceLocator* service_locator);

  friend class IClassManager;
  static ObjectBase::Ref Create(ServiceLocator* service_locator);

  // Update the highest influences and highest matrix index.
  void UpdateInfo() const;

  // Frees all the influences and matrices.
  void FreeAll();

  // The vertex influences.
  InfluencesArray influences_array_;

  // The inverse bind poses.
  MatrixArray inverse_bind_pose_matrices_;

  // The highest matrix index.
  mutable unsigned highest_matrix_index_;

  // The highest number of influences.
  mutable unsigned highest_influences_;

  // True of the highest matrix index and highest influences is valid.
  mutable bool info_valid_;

  // Manager for weak pointers to us.
  WeakPointerType::WeakPointerManager weak_pointer_manager_;

  O3D_DECL_CLASS(Skin, NamedObject);
  DISALLOW_COPY_AND_ASSIGN(Skin);
};

// A Param that holds a weak reference to a Skin.
class ParamSkin : public TypedRefParam<Skin> {
 public:
  typedef SmartPointer<ParamSkin> Ref;

  ParamSkin(ServiceLocator* service_locator, bool dynamic, bool read_only)
      : TypedRefParam<Skin>(service_locator, dynamic, read_only) {}

 private:
  friend class IClassManager;
  static ObjectBase::Ref Create(ServiceLocator* service_locator);

  O3D_DECL_CLASS(ParamSkin, RefParamBase);
};

// A SkinEval is a VertexSource that takes its Streams, a ParamArray of Matrix4s
// and a Skin and skins the vertices in its streams storing the results in bound
// output streams.
class SkinEval : public VertexSource {
 public:
  static const char* kMatricesParamName;
  static const char* kSkinParamName;
  static const char* kBaseParamName;

  Skin* skin() const {
    return skin_param_->value();
  }

  void set_skin(Skin* skin) {
    skin_param_->set_value(skin);
  }

  ParamArray* matrices() const {
    return matrices_param_->value();
  }

  void set_matrices(ParamArray* matrices) {
    matrices_param_->set_value(matrices);
  }

  Matrix4 base() const {
    return base_param_->value();
  }

  void set_base(const Matrix4& base) {
    base_param_->set_value(base);
  }

  // Binds the field of SourceBuffer and defines how the data in the buffer
  // should be accessed and interpreted.
  bool SetVertexStream(Stream::Semantic semantic,
                       int semantic_index,
                       Field* field,
                       unsigned int start_index);

  // Removes a vertex stream from this primitive.
  // Returns true if the specified stream existed.
  bool RemoveVertexStream(Stream::Semantic stream_semantic,
                          int semantic_index);

  // Searches the vertex streams bound to the shape for one with the given
  // stream semantic.  If a stream is not found then it returns NULL.
  const Stream* GetVertexStream(Stream::Semantic stream_semantic,
                                int semantic_index) const;

  // Updates all the VertexBuffers bound to streams on this VertexSource.
  void UpdateStreams();

  // Updates the VertexBuffers bound to streams on this VertexSource.
  void UpdateOutputs();

  // Overriden from VertexSource.
  virtual ParamVertexBufferStream* GetVertexStreamParam(
      Stream::Semantic semantic,
      int semantic_index) const;

  const StreamParamVector& vertex_stream_params() const {
    return vertex_stream_params_;
  }

 protected:
  // Overridden from ParamObject
  // For the given Param, returns all the inputs that affect that param through
  // this ParamObject.
  virtual void ConcreteGetInputsForParam(const Param* param,
                                         ParamVector* inputs) const;

  // Overridden from ParamCollection
  // For the given Param, returns all the outputs that the given param will
  // affect through this ParamObject.
  virtual void ConcreteGetOutputsForParam(const Param* param,
                                          ParamVector* outputs) const;

 private:
  class SlaveParamVertexBufferStream : public ParamVertexBufferStream {
   public:
    SlaveParamVertexBufferStream(ServiceLocator* service_locator,
                                 SkinEval* master,
                                 Stream* stream)
        : ParamVertexBufferStream(service_locator, stream, true, false),
          master_(master) {
      set_owner(master);
    }

    virtual void ComputeValue() {
      master_->UpdateOutputs();
    }

   private:
    SkinEval* master_;
    DISALLOW_COPY_AND_ASSIGN(SlaveParamVertexBufferStream);
  };

  typedef std::vector<Matrix4> Matrix4Vector;

  explicit SkinEval(ServiceLocator* service_locator);

  friend class IClassManager;
  static ObjectBase::Ref Create(ServiceLocator* service_locator);

  // Returns true if param is one of the Stream params on this SkinEval.
  bool ParamIsStreamParam(const Param* param) const;

  void DoSkinning(Skin* skin);

  // The streams on this SkinEval
  StreamParamVector vertex_stream_params_;

  // The array of bone matrices
  ParamParamArray::Ref matrices_param_;

  // The base matrix that will be used to keep the vertices in object space.
  ParamMatrix4::Ref base_param_;

  // The skin
  ParamSkin::Ref skin_param_;

  // A place to store the bone calulations. We keep this in the struct
  // so we don't have to allocate it every time.
  Matrix4Vector bones_;

  // This class helps manage each stream. Because allocating memory is slow
  // we keep these around across calls and reuse them in place by calling
  // Init.
  class StreamInfo {
   public:
    StreamInfo();

    // Locks the stream.
    bool Init(const Stream& stream, Buffer::AccessMode access_mode);

    // Unlocks the stream.
    void Uninit();

    // Multiplies the current value by the matrix and stores it in result and
    // advances to the next value.
    void Compute(const Matrix4& matrix) {
      compute_function_(&result_[0], values_, matrix);
      Advance();
    }

    // Copies the result from source and advances to the next value.
    void Copy(const StreamInfo& source) {
      copy_function_(values_, &source.result_[0]);
      Advance();
    }

   private:
    // Advances the internal counter to the next set.
    void Advance() {
      values_ = reinterpret_cast<float*>(reinterpret_cast<char*>(
          values_) + stride_);
    }

    // A pointer to function the multipies the source by the matrix and stores
    // the result in destination.
    typedef void (*ComputeFunction)(float* destination,
                                    const float* source,
                                    const Matrix4& matrix);

    // A pointer to a function that copies a 3 or 4 floats from the source to
    // the destination.
    typedef void (*CopyFunction)(float* destination, const float* source);

    ComputeFunction compute_function_;
    CopyFunction copy_function_;
    void* data_;
    Buffer* buffer_;
    float* values_;
    unsigned stride_;
    float result_[4];
  };

  typedef std::vector<StreamInfo> StreamInfoVector;
  typedef std::vector<StreamInfoVector> StreamInfoVectorVector;

  StreamInfoVector input_stream_infos_;
  StreamInfoVectorVector output_stream_infos_;

  O3D_DECL_CLASS(SkinEval, VertexSource);
  DISALLOW_COPY_AND_ASSIGN(SkinEval);
};

}  // namespace o3d

#endif  // O3D_CORE_CROSS_SKIN_H_