03d2d3a5ea180b937e3be9b750d2f4f26e655017
[blender-staging.git] / intern / audaspace / intern / AUD_AnimateableProperty.cpp
1 /*
2  * $Id$
3  *
4  * ***** BEGIN GPL LICENSE BLOCK *****
5  *
6  * Copyright 2009-2011 Jörg Hermann Müller
7  *
8  * This file is part of AudaSpace.
9  *
10  * Audaspace is free software; you can redistribute it and/or modify
11  * it under the terms of the GNU General Public License as published by
12  * the Free Software Foundation; either version 2 of the License, or
13  * (at your option) any later version.
14  *
15  * AudaSpace is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU General Public License for more details.
19  *
20  * You should have received a copy of the GNU General Public License
21  * along with Audaspace; if not, write to the Free Software Foundation,
22  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
23  *
24  * ***** END GPL LICENSE BLOCK *****
25  */
26
27 /** \file audaspace/intern/AUD_AnimateableProperty.cpp
28  *  \ingroup audaspaceintern
29  */
30
31
32 #include "AUD_AnimateableProperty.h"
33
34 #include <cstring>
35 #include <cmath>
36
37 AUD_AnimateableProperty::AUD_AnimateableProperty(int count) :
38         AUD_Buffer(count * sizeof(float)), m_count(count), m_isAnimated(false), m_changed(false)
39 {
40         memset(getBuffer(), 0, count * sizeof(float));
41
42         pthread_mutexattr_t attr;
43         pthread_mutexattr_init(&attr);
44         pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
45
46         pthread_mutex_init(&m_mutex, &attr);
47
48         pthread_mutexattr_destroy(&attr);
49 }
50
51 AUD_AnimateableProperty::~AUD_AnimateableProperty()
52 {
53         pthread_mutex_destroy(&m_mutex);
54 }
55
56 void AUD_AnimateableProperty::lock()
57 {
58         pthread_mutex_lock(&m_mutex);
59 }
60
61 void AUD_AnimateableProperty::unlock()
62 {
63         pthread_mutex_unlock(&m_mutex);
64 }
65
66 void AUD_AnimateableProperty::write(const float* data)
67 {
68         lock();
69
70         m_isAnimated = false;
71         m_changed = true;
72         memcpy(getBuffer(), data, m_count * sizeof(float));
73
74         unlock();
75 }
76
77 void AUD_AnimateableProperty::write(const float* data, int position, int count)
78 {
79         lock();
80
81         m_isAnimated = true;
82
83         int pos = getSize() / (sizeof(float) * m_count);
84
85         assureSize((count + position) * m_count * sizeof(float), true);
86
87         float* buf = getBuffer();
88
89         memcpy(buf + position * m_count, data, count * m_count * sizeof(float));
90
91         for(int i = pos; i < position; i++)
92                 memcpy(buf + i * m_count, buf + (pos - 1) * m_count, m_count * sizeof(float));
93
94         unlock();
95 }
96
97 void AUD_AnimateableProperty::read(float position, float* out)
98 {
99         lock();
100
101         if(!m_isAnimated)
102         {
103                 memcpy(out, getBuffer(), m_count * sizeof(float));
104                 unlock();
105                 return;
106         }
107
108         float last = (getSize() / (sizeof(float) * m_count) - 1);
109         float t = position - floor(position);
110
111         if(position > last)
112         {
113                 position = last;
114                 t = 0;
115         }
116
117         if(t == 0)
118         {
119                 memcpy(out, getBuffer() + int(floor(position)) * m_count, m_count * sizeof(float));
120         }
121         else
122         {
123                 int pos = int(floor(position)) * m_count;
124                 float t2 = t * t;
125                 float t3 = t2 * t;
126                 float m0, m1;
127                 float* p0;
128                 float* p1 = getBuffer() + pos;
129                 float* p2;
130                 float* p3;
131
132                 if(pos == 0)
133                         p0 = p1;
134                 else
135                         p0 = p1 - m_count;
136
137                 if(pos > last)
138                 {
139                         p3 = p2 = p1;
140                 }
141                 else
142                 {
143                         p2 = p1 + m_count;
144                         if(pos + m_count > last)
145                                 p3 = p2;
146                         else
147                                 p3 = p2 + m_count;
148                 }
149
150                 for(int i = 0; i < m_count; i++)
151                 {
152                         m0 = (p2[i] - p0[i]) / 2.0f;
153                         m1 = (p3[i] - p1[i]) / 2.0f;
154
155                         out[i] = (2 * t3 - 3 * t2 + 1) * p0[i] + (-2 * t3 + 3 * t2) * p1[i] +
156                                          (t3 - 2 * t2 + t) * m0 + (t3 - t2) * m1;
157                 }
158         }
159
160         unlock();
161 }
162
163 bool AUD_AnimateableProperty::isAnimated() const
164 {
165         return m_isAnimated;
166 }
167
168 bool AUD_AnimateableProperty::hasChanged()
169 {
170         if(m_isAnimated)
171                 return true;
172
173         bool result = m_changed;
174         m_changed = false;
175         return result;
176 }