beginning CD implementation
[chaz/yoink] / src / Character.cc
1
2 /*******************************************************************************
3
4 Copyright (c) 2009, Charles McGarvey
5 All rights reserved.
6
7 Redistribution and use in source and binary forms, with or without
8 modification, are permitted provided that the following conditions are met:
9
10 * Redistributions of source code must retain the above copyright notice,
11 this list of conditions and the following disclaimer.
12 * Redistributions in binary form must reproduce the above copyright notice,
13 this list of conditions and the following disclaimer in the documentation
14 and/or other materials provided with the distribution.
15
16 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
17 AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18 IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
20 FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21 DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
22 SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
23 CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
24 OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
25 OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26
27 *******************************************************************************/
28
29 #include <iostream>
30
31 #include "Character.hh"
32 #include "Log.hh"
33
34
35 struct SpringForce
36 {
37 explicit SpringForce(Mf::Vector2 x) :
38 location(x) {}
39
40 const Mf::Vector2& operator () (const Mf::LinearState<2>& state)
41 {
42 Mf::Vector2 x = state.position - location;
43 Mf::Scalar mag = x.length();
44 Mf::Scalar d = 50.0;
45
46 // spring:
47 //current.force += -15.0 * x - 1.5 * current.velocity;
48 force = -20.0 * (mag - d) * (x / mag) - 2.0 * state.velocity;
49
50 return force;
51 }
52
53 private:
54
55 Mf::Vector2 force;
56 Mf::Vector2 location;
57 };
58
59 struct ResistanceForce
60 {
61 explicit ResistanceForce(Mf::Scalar scale = 1.0) :
62 k(scale) {}
63
64 const Mf::Vector2& operator () (const Mf::LinearState<2>& state)
65 {
66 force = -k * state.velocity;
67 return force;
68 }
69
70 private:
71
72 Mf::Vector2 force;
73 Mf::Scalar k;
74 };
75
76
77 Character::Character(const std::string& name) :
78 tilemap(name),
79 animation(name)
80 {
81 current.init();
82
83 current.mass = 1.0;
84 current.inverseMass = 1.0 / current.mass;
85
86 // forces
87 current.force = Mf::Vector2(0.0, 0.0);
88 current.forces.push_back(SpringForce(Mf::Vector2(500.0, 200.0)));
89 current.forces.push_back(ResistanceForce(2.0));
90 current.forces.push_back(Mf::LinearState<2>::GravityForce(-1000.0));
91
92 // starting position
93 current.position = Mf::Vector2(64.0, 64.0);
94 current.momentum = Mf::Vector2(0.0, 0.0);
95 current.recalculate();
96
97 previous = current;
98 }
99
100
101 void Character::update(Mf::Scalar t, Mf::Scalar dt)
102 {
103 previous = current;
104
105 //Mf::Vector2 x = current.position - Mf::Vector2(500.0, 200.0);
106 //Mf::Scalar mag = x.length();
107 //Mf::Scalar d = 50.0;
108
109 //// gravity:
110 //current.force = Mf::Vector2(0.0, -2000.0);
111 //// spring:
112 ////current.force += -15.0 * x - 1.5 * current.velocity;
113 //current.force += -20.0 * (mag - d) * (x / mag) - 2.0 * current.velocity;
114 //// internal:
115 //current.force += userForce;
116 //current.recalculate();
117 //std::cout << "force: " << current.momentum << std::endl;
118
119 //Mf::euler<State,Derivative>(current, t, dt);
120
121 current.integrate(t, dt);
122 animation.update(t, dt);
123
124 Mf::Vector3 center(current.position[0], current.position[1], z);
125 Mf::Vector3 a(current.position[0] - 16.0, current.position[1] - 16.0, z);
126 Mf::Vector3 b(current.position[0] + 16.0, current.position[1] + 16.0, z);
127
128 aabb_.init(a, b);
129 sphere_.init(center, a);
130 }
131
132
133 void Character::draw(Mf::Scalar alpha) const
134 {
135 Mf::Vector2 position = cml::lerp(previous.position, current.position, alpha);
136
137 //glColor3f(1.0f, 1.0f, 1.0f);
138 tilemap.bind();
139
140 Tilemap::Index frame = animation.getFrame();
141
142 Tilemap::Orientation orientation = Tilemap::NORMAL;
143
144 if (current.velocity[0] < 0.0) orientation = Tilemap::REVERSE;
145
146 Mf::Scalar coords[8];
147 tilemap.getTileCoords(frame, coords, orientation);
148
149 Mf::Scalar s = 16.0;
150
151 glBegin(GL_TRIANGLE_FAN);
152 glTexCoord2f(coords[0], coords[1]);
153 glVertex3(position[0]-s, position[1]-s, z);
154 glTexCoord2f(coords[2], coords[3]);
155 glVertex3(position[0]+s, position[1]-s, z);
156 glTexCoord2f(coords[4], coords[5]);
157 glVertex3(position[0]+s, position[1]+s, z);
158 glTexCoord2f(coords[6], coords[7]);
159 glVertex3(position[0]-s, position[1]+s, z);
160 glEnd();
161
162 //glColor3f(0.0f, 0.0f, 0.0f);
163 Mf::Texture::resetBind();
164
165 glBegin(GL_TRIANGLES);
166 glVertex3(480.0, 190.0, 64.0);
167 glVertex3(520.0, 190.0, 64.0);
168 glVertex3(500.0, 210.0, 64.0);
169 glEnd();
170
171 //glColor3f(1.0f, 1.0f, 1.0f);
172 }
173
174
175 bool Character::isInsideAabb(const Mf::Aabb& aabb) const
176 {
177 // make sure the entity is fully inside the volume
178 if (!(aabb_.max[0] < aabb.max[0] &&
179 aabb_.min[0] > aabb.min[0] &&
180 aabb_.max[1] < aabb.max[1] &&
181 aabb_.min[1] > aabb.min[1] &&
182 aabb_.max[2] < aabb.max[2] &&
183 aabb_.min[2] > aabb.min[2]))
184 {
185 return false;
186 }
187
188 return true;
189 }
190
191 int Character::getOctant(const Mf::Aabb& aabb) const
192 {
193 int octantNum = -1;
194
195 Mf::Plane::Halfspace halfspace;
196
197 Mf::Plane xy = aabb.getPlaneXY();
198 halfspace = xy.intersects(sphere_);
199 if (halfspace == Mf::Plane::INTERSECT)
200 {
201 halfspace = xy.intersects(aabb_);
202 }
203
204 if (halfspace == Mf::Plane::POSITIVE)
205 {
206 Mf::Plane xz = aabb.getPlaneXZ();
207 halfspace = xz.intersects(sphere_);
208 if (halfspace == Mf::Plane::INTERSECT)
209 {
210 halfspace = xz.intersects(aabb_);
211 }
212
213 if (halfspace == Mf::Plane::POSITIVE)
214 {
215 Mf::Plane yz = aabb.getPlaneYZ();
216 halfspace = yz.intersects(sphere_);
217 if (halfspace == Mf::Plane::INTERSECT)
218 {
219 halfspace = yz.intersects(aabb_);
220 }
221
222 if (halfspace == Mf::Plane::POSITIVE)
223 {
224 octantNum = 2;
225 }
226 else if (halfspace == Mf::Plane::NEGATIVE)
227 {
228 octantNum = 3;
229 }
230 }
231 else if (halfspace == Mf::Plane::NEGATIVE)
232 {
233 Mf::Plane yz = aabb.getPlaneYZ();
234 halfspace = yz.intersects(sphere_);
235 if (halfspace == Mf::Plane::INTERSECT)
236 {
237 halfspace = yz.intersects(aabb_);
238 }
239
240 if (halfspace == Mf::Plane::POSITIVE)
241 {
242 octantNum = 1;
243 }
244 else if (halfspace == Mf::Plane::NEGATIVE)
245 {
246 octantNum = 0;
247 }
248 }
249 }
250 else if (halfspace == Mf::Plane::NEGATIVE)
251 {
252 Mf::Plane xz = aabb.getPlaneXZ();
253 halfspace = xz.intersects(sphere_);
254 if (halfspace == Mf::Plane::INTERSECT)
255 {
256 halfspace = xz.intersects(aabb_);
257 }
258
259 if (halfspace == Mf::Plane::POSITIVE)
260 {
261 Mf::Plane yz = aabb.getPlaneYZ();
262 halfspace = yz.intersects(sphere_);
263 if (halfspace == Mf::Plane::INTERSECT)
264 {
265 halfspace = yz.intersects(aabb_);
266 }
267
268 if (halfspace == Mf::Plane::POSITIVE)
269 {
270 octantNum = 6;
271 }
272 else if (halfspace == Mf::Plane::NEGATIVE)
273 {
274 octantNum = 7;
275 }
276 }
277 else if (halfspace == Mf::Plane::NEGATIVE)
278 {
279 Mf::Plane yz = aabb.getPlaneYZ();
280 halfspace = yz.intersects(sphere_);
281 if (halfspace == Mf::Plane::INTERSECT)
282 {
283 halfspace = yz.intersects(aabb_);
284 }
285
286 if (halfspace == Mf::Plane::POSITIVE)
287 {
288 octantNum = 5;
289 }
290 else if (halfspace == Mf::Plane::NEGATIVE)
291 {
292 octantNum = 4;
293 }
294 }
295 }
296
297 return octantNum;
298 }
299
300
301 /** vim: set ts=4 sw=4 tw=80: *************************************************/
302
This page took 0.045539 seconds and 4 git commands to generate.