00001
00002 #ifndef DOLOG
00003
00004 #undef DOLOG
00005 #endif
00006
00007
00008 #include <fstream>
00009 #include <stdexcept>
00010
00011 #include "PhysicalObject.h"
00012
00013
00018 PhysicalObject::PhysicalObject(bool enablePhysics)
00019 : mTransform(),
00020 mInverseTransform(),
00021 mPhysicsOn(enablePhysics),
00022 mMass(INFINITY),
00023 mPosition(),
00024 mScaling(1.0f),
00025 mRotation(),
00026 mVelocity(),
00027 mAngularVelocity(),
00028 mTime(0.0f)
00029 {
00030 }
00031
00032
00035 PhysicalObject::~PhysicalObject()
00036 {
00037 }
00038
00039
00042 void PhysicalObject::updateProperties(float t)
00043 {
00044 LLOG(mTime);
00045
00046 assert(t >= -0.0f && t >= mTime - EPSILON);
00047
00048 float dt = t - mTime;
00049 Vec3f dv(0, 0, 0);
00050 Vec3f dw(0, 0, 0);
00051 LLOG("Updating properties to time : " << t << " dt = " << dt);
00052 if (dt < EPSILON)
00053 {
00054 LLOG("no need for update");
00055 return;
00056 }
00057
00058
00059
00060 const Vec3f vw = mAngularVelocity.cross(WORLD_UP * -BALL_RADIUS);
00061 const Vec3f v_perimeter = vw + mVelocity;
00062 bool adjustAngularVelocity = false;
00063 LLOG("v_p = " << v_perimeter << " |v_p| = " << v_perimeter.length());
00064 LLOG("w x r = " << vw << " |w x r| = " << vw.length());
00065 if (mVelocity.length() < PHYS_EPS)
00066 {
00067 if (mVelocity.length() > EPSILON)
00068 {
00069 LLOG("\n\n\n");
00070
00071 LLOG("\nSTOPPING\n\n\n");
00072 }
00073
00074 mAngularVelocity = Vec3f(0, 0, 0);
00075 mVelocity = Vec3f(0, 0, 0);
00076 mTime = t;
00077
00078
00079 resetTransform();
00080 scale(mScaling, mScaling, mScaling);
00081 rotate(mRotation.length(), mRotation);
00082 translate(mPosition);
00083 return;
00084 }
00085 else if (v_perimeter.length() < PHYS_EPS)
00086 {
00087 LLOG("ROLLS");
00088
00089 if (mVelocity.length() > EPSILON)
00090 dv = mVelocity.normal() * -MUE_ROLLING * GRAVITY * dt;
00091 adjustAngularVelocity = true;
00092 }
00093 else
00094 {
00095 LLOG("SLIDES");
00096
00097 Vec3f f_friction(0, 0, 0);
00098 if (v_perimeter.length() > EPSILON)
00099 {
00100
00101
00102
00103
00104 f_friction = v_perimeter.normal() * -MUE_SLIDING * GRAVITY * mMass;
00105 }
00106 LLOG("F = " << f_friction << " |F| = " << f_friction.length());
00107
00108 dw = (WORLD_UP * -BALL_RADIUS).cross(f_friction) * 2.5f * dt / (mMass * BALL_RADIUS * BALL_RADIUS);
00109 if ((WORLD_UP * -BALL_RADIUS).cross(f_friction).length() < PHYS_EPS)
00110 {
00111 LLOG("ROTATES");
00112
00113 f_friction = mAngularVelocity.cross(WORLD_UP_MASK.normal()) * -MUE_SLIDING * GRAVITY * mMass;
00114 dw = (WORLD_UP_MASK.normal() * CONTACT_RADIUS).cross(f_friction) * 2.5f * dt / (mMass * BALL_RADIUS * BALL_RADIUS);
00115 }
00116
00117 float Ekin = mVelocity.dot(mVelocity) + 0.4f * BALL_RADIUS * BALL_RADIUS * mAngularVelocity.dot(mAngularVelocity);
00118 float dErot = 0.4f * BALL_RADIUS * BALL_RADIUS * (mAngularVelocity + dw).dot(mAngularVelocity + dw);
00119 float dEfrict = MUE_SLIDING * GRAVITY * v_perimeter.length() * dt;
00120 LLOG("Ekin = " << Ekin);
00121 LLOG("dErot = " << dErot);
00122 LLOG("dEfrict = " << dEfrict);
00123 if (v_perimeter.length() > EPSILON)
00124 {
00125 float dE = Ekin - dErot - dEfrict;
00126 if (dE < 0.0f)
00127 dv = - v_perimeter.normal() * (mVelocity.length() + sqrt(- dE));
00128 else
00129 dv = - v_perimeter.normal() * (mVelocity.length() - sqrt(dE));
00130 }
00131 }
00132 LLOG("dv = " << dv << " |dv| = " << dv.length());
00133 LLOG("dw = " << dw << " |dw| = " << dw.length());
00134
00135
00136 Vec3f dr;
00137
00138 Vec3f ds = dv * 0.5f * dt + mVelocity * dt;
00139 LLOG("ds = " << ds << " |ds| = " << ds.length());
00140
00141
00142 if (!adjustAngularVelocity)
00143 {
00144 mRotation += dw * 0.5f * dt + mAngularVelocity * dt;
00145 LLOG("dr = " << (dw * 0.5f * dt + mAngularVelocity * dt)
00146 << " |dr| = " << (dw * 0.5f * dt + mAngularVelocity * dt).length());
00147
00148
00149 resetTransform();
00150 scale(mScaling, mScaling, mScaling);
00151 rotate(mRotation.length(), mRotation);
00152 translate(mPosition + WORLD_UP_MASK.scaled(ds));
00153 }
00154
00155
00156 mVelocity = WORLD_UP_MASK.scaled(mVelocity + dv);
00157 Vec3f oldAV = mAngularVelocity;
00158 mAngularVelocity += dw;
00159 mTime = t;
00160
00161
00162 const Vec3f v_perimeter2 = mAngularVelocity.cross(WORLD_UP * -BALL_RADIUS) + mVelocity;
00163 if (adjustAngularVelocity || v_perimeter.dot(v_perimeter - v_perimeter2) * v_perimeter2.dot(v_perimeter - v_perimeter2) < 0.0f)
00164 {
00165 LLOG("adjusting w : " << mAngularVelocity << "(" << mAngularVelocity.length() << ") -> "
00166 << (WORLD_UP * BALL_RADIUS).cross(mVelocity) / (BALL_RADIUS * BALL_RADIUS)
00167 << "(" << (WORLD_UP * BALL_RADIUS).cross(mVelocity).length() / (BALL_RADIUS * BALL_RADIUS) << ")");
00168
00169
00170 mAngularVelocity = (WORLD_UP * BALL_RADIUS).cross(mVelocity) / (BALL_RADIUS * BALL_RADIUS);
00171 dw = mAngularVelocity - oldAV;
00172 }
00173
00174
00175 if (adjustAngularVelocity)
00176 {
00177 mRotation += dw * 0.5f * dt + oldAV * dt;
00178
00179 resetTransform();
00180 scale(mScaling, mScaling, mScaling);
00181 rotate(mRotation.length(), mRotation);
00182 translate(mPosition + WORLD_UP_MASK.scaled(ds));
00183 }
00184
00185 LLOG("result:");
00186
00187
00188
00189 LLOG("\n");
00190 }
00191
00192
00197 void PhysicalObject::writeDump(std::ostream & outs)
00198 {
00199 if (!mPhysicsOn)
00200 {
00201 throw std::logic_error("Physics must be on to write to file");
00202 }
00203
00204 int magic = 0x316a626f;
00205 outs.write(reinterpret_cast<const char *>(&magic), sizeof(int));
00206
00207 outs.write(reinterpret_cast<const char *>(&mTransform), sizeof(Matrix));
00208 outs.write(reinterpret_cast<const char *>(&mInverseTransform), sizeof(Matrix));
00209 outs.write(reinterpret_cast<const char *>(&mMass), sizeof(float));
00210 outs.write(reinterpret_cast<const char *>(&mPosition), sizeof(Vec3f));
00211 outs.write(reinterpret_cast<const char *>(&mScaling), sizeof(float));
00212 outs.write(reinterpret_cast<const char *>(&mRotation), sizeof(Vec3f));
00213 outs.write(reinterpret_cast<const char *>(&mVelocity), sizeof(Vec3f));
00214 outs.write(reinterpret_cast<const char *>(&mAngularVelocity), sizeof(Vec3f));
00215 outs.write(reinterpret_cast<const char *>(&mTime), sizeof(float));
00216 }
00217
00218
00223 void PhysicalObject::readDump(std::istream & ins)
00224 {
00225 if (!mPhysicsOn)
00226 {
00227 throw std::logic_error("Physics must be on to read from file");
00228 }
00229
00230 int magic;
00231 ins.read(reinterpret_cast<char *>(&magic), sizeof(int));
00232 if (magic != 0x316a626f)
00233 {
00234 throw std::logic_error("Could not find object data");
00235 }
00236 ins.clear();
00237
00238 ins.read(reinterpret_cast<char *>(&mTransform), sizeof(Matrix));
00239 ins.clear();
00240 ins.read(reinterpret_cast<char *>(&mInverseTransform), sizeof(Matrix));
00241 ins.clear();
00242 ins.read(reinterpret_cast<char *>(&mMass), sizeof(float));
00243 ins.clear();
00244 ins.read(reinterpret_cast<char *>(&mPosition), sizeof(Vec3f));
00245 ins.clear();
00246 ins.read(reinterpret_cast<char *>(&mScaling), sizeof(float));
00247 ins.clear();
00248 ins.read(reinterpret_cast<char *>(&mRotation), sizeof(Vec3f));
00249 ins.clear();
00250 ins.read(reinterpret_cast<char *>(&mVelocity), sizeof(Vec3f));
00251 ins.clear();
00252 ins.read(reinterpret_cast<char *>(&mAngularVelocity), sizeof(Vec3f));
00253 ins.clear();
00254 ins.read(reinterpret_cast<char *>(&mTime), sizeof(float));
00255 ins.clear();
00256 }
00257
00258