summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rwxr-xr-x2d/_collisions/polygon_polygon/dist/output.wasmbin58079 -> 58262 bytes
-rw-r--r--2d/_collisions/polygon_polygon/main.cpp2
-rw-r--r--2d/rigidbody/rigidbody_1.html2
-rwxr-xr-x2d/rigidbody/rigidbody_1/dist/output.wasmbin48801 -> 49033 bytes
-rw-r--r--2d/rigidbody/rigidbody_1/main.cpp7
-rw-r--r--2d/rigidbody/rigidbody_1/snippet3.cpp2
-rwxr-xr-x2d/rigidbody/rigidbody_2/dist/output.wasmbin50226 -> 50452 bytes
-rw-r--r--2d/rigidbody/rigidbody_2/main.cpp2
-rwxr-xr-x2d/rigidbody/rigidbody_3/dist/output.wasmbin49458 -> 49653 bytes
-rw-r--r--2d/rigidbody/rigidbody_3/main.cpp2
-rw-r--r--3d/rigidbody.html51
-rw-r--r--3d/rigidbody.html.content51
-rwxr-xr-x3d/rigidbody/dist/output.wasmbin43167 -> 48113 bytes
-rw-r--r--3d/rigidbody/main.cpp110
-rw-r--r--resources.html.content12
-rw-r--r--shared_cpp/mathlib.cpp28
-rw-r--r--shared_cpp/mathlib.h10
17 files changed, 222 insertions, 57 deletions
diff --git a/2d/_collisions/polygon_polygon/dist/output.wasm b/2d/_collisions/polygon_polygon/dist/output.wasm
index a047d19..055fbb7 100755
--- a/2d/_collisions/polygon_polygon/dist/output.wasm
+++ b/2d/_collisions/polygon_polygon/dist/output.wasm
Binary files differ
diff --git a/2d/_collisions/polygon_polygon/main.cpp b/2d/_collisions/polygon_polygon/main.cpp
index 620edaa..9cb3eb2 100644
--- a/2d/_collisions/polygon_polygon/main.cpp
+++ b/2d/_collisions/polygon_polygon/main.cpp
@@ -72,7 +72,7 @@ struct Rigidbody {
float32 impulseDtSeconds = nextTimeAppliedSeconds - i.timeAppliedSeconds;
Vector2 forceToApply = i.force * (impulseDtSeconds / i.timeOfApplicationSeconds);
- force += forceToApply * impulseDtSeconds;
+ force += forceToApply;
i.timeAppliedSeconds = nextTimeAppliedSeconds;
diff --git a/2d/rigidbody/rigidbody_1.html b/2d/rigidbody/rigidbody_1.html
index b98d292..0d50904 100644
--- a/2d/rigidbody/rigidbody_1.html
+++ b/2d/rigidbody/rigidbody_1.html
@@ -200,7 +200,7 @@
<span class="code_comment">// to calculate the fractional amount of force that was applied in this frame.</span>
<span class="code_keyword">float32</span> impulseDtSeconds = nextTimeAppliedSeconds - i.timeAppliedSeconds;
<span class="code_keyword">Vector2</span> forceToApply = i.force * (impulseDtSeconds / i.timeOfApplicationSeconds);
- force += forceToApply * impulseDtSeconds;
+ force += forceToApply;
i.timeAppliedSeconds = nextTimeAppliedSeconds;
}
diff --git a/2d/rigidbody/rigidbody_1/dist/output.wasm b/2d/rigidbody/rigidbody_1/dist/output.wasm
index f6625a9..b9f4c37 100755
--- a/2d/rigidbody/rigidbody_1/dist/output.wasm
+++ b/2d/rigidbody/rigidbody_1/dist/output.wasm
Binary files differ
diff --git a/2d/rigidbody/rigidbody_1/main.cpp b/2d/rigidbody/rigidbody_1/main.cpp
index 88c322c..a327fee 100644
--- a/2d/rigidbody/rigidbody_1/main.cpp
+++ b/2d/rigidbody/rigidbody_1/main.cpp
@@ -61,8 +61,7 @@ struct Rigidbody {
float32 impulseDtSeconds = nextTimeAppliedSeconds - i.timeAppliedSeconds;
Vector2 forceToApply = i.force * (impulseDtSeconds / i.timeOfApplicationSeconds);
- force += forceToApply * impulseDtSeconds;
-
+ force += forceToApply;
i.timeAppliedSeconds = nextTimeAppliedSeconds;
}
@@ -301,8 +300,8 @@ EM_BOOL onMouseMove(int eventType, const EmscriptenMouseEvent *mouseEvent, void
return true;
}
- pointer.force.x = static_cast<float32>(mouseEvent->movementX) * 100000.f;
- pointer.force.y = static_cast<float32>(-mouseEvent->movementY) * 100000.f;
+ pointer.force.x = static_cast<float32>(mouseEvent->movementX) * 1000.f;
+ pointer.force.y = static_cast<float32>(-mouseEvent->movementY) * 1000.f;
pointer.body.position.x = static_cast<float32>(mouseEvent->targetX);
pointer.body.position.y = static_cast<float32>(600.f - mouseEvent->targetY);
diff --git a/2d/rigidbody/rigidbody_1/snippet3.cpp b/2d/rigidbody/rigidbody_1/snippet3.cpp
index 4727a9a..d3ecc4f 100644
--- a/2d/rigidbody/rigidbody_1/snippet3.cpp
+++ b/2d/rigidbody/rigidbody_1/snippet3.cpp
@@ -31,7 +31,7 @@ struct Rigidbody {
// to calculate the fractional amount of force that was applied in this frame.
float32 impulseDtSeconds = nextTimeAppliedSeconds - i.timeAppliedSeconds;
Vector2 forceToApply = i.force * (impulseDtSeconds / i.timeOfApplicationSeconds);
- force += forceToApply * impulseDtSeconds;
+ force += forceToApply;
i.timeAppliedSeconds = nextTimeAppliedSeconds;
}
diff --git a/2d/rigidbody/rigidbody_2/dist/output.wasm b/2d/rigidbody/rigidbody_2/dist/output.wasm
index 29c319a..fb79e45 100755
--- a/2d/rigidbody/rigidbody_2/dist/output.wasm
+++ b/2d/rigidbody/rigidbody_2/dist/output.wasm
Binary files differ
diff --git a/2d/rigidbody/rigidbody_2/main.cpp b/2d/rigidbody/rigidbody_2/main.cpp
index 123cf7e..44a3c53 100644
--- a/2d/rigidbody/rigidbody_2/main.cpp
+++ b/2d/rigidbody/rigidbody_2/main.cpp
@@ -69,7 +69,7 @@ struct Rigidbody {
float32 impulseDtSeconds = nextTimeAppliedSeconds - i.timeAppliedSeconds;
Vector2 forceToApply = i.force * (impulseDtSeconds / i.timeOfApplicationSeconds);
- force += forceToApply * impulseDtSeconds;
+ force += forceToApply;
// New! Increment the torque for each force
torque += i.pointOfApplication.getPerp().dot(forceToApply);
diff --git a/2d/rigidbody/rigidbody_3/dist/output.wasm b/2d/rigidbody/rigidbody_3/dist/output.wasm
index b89435a..0a8a974 100755
--- a/2d/rigidbody/rigidbody_3/dist/output.wasm
+++ b/2d/rigidbody/rigidbody_3/dist/output.wasm
Binary files differ
diff --git a/2d/rigidbody/rigidbody_3/main.cpp b/2d/rigidbody/rigidbody_3/main.cpp
index e34f444..2a0af24 100644
--- a/2d/rigidbody/rigidbody_3/main.cpp
+++ b/2d/rigidbody/rigidbody_3/main.cpp
@@ -72,7 +72,7 @@ struct Rigidbody {
float32 impulseDtSeconds = nextTimeAppliedSeconds - i.timeAppliedSeconds;
Vector2 forceToApply = i.force * (impulseDtSeconds / i.timeOfApplicationSeconds);
- force += forceToApply * impulseDtSeconds;
+ force += forceToApply;
torque += i.pointOfApplication.getPerp().dot(forceToApply);
i.timeAppliedSeconds = nextTimeAppliedSeconds;
diff --git a/3d/rigidbody.html b/3d/rigidbody.html
index db91bd0..68244de 100644
--- a/3d/rigidbody.html
+++ b/3d/rigidbody.html
@@ -69,26 +69,37 @@
<article>
<h1>Rigidbody in 3D</h1>
<section>
- <section>
- <h2>
- Live Example
- </h2>
- <div class="opengl_canvas_container">
- <canvas id="gl_canvas" width="800" height="600"></canvas>
- <button id="gl_canvas_play" class="play_button">
- Play
- </button>
- <button id="gl_canvas_stop" class="stop_button">
- Stop
- </button>
- </div>
-
- <footer id="references">
- <h2>References</h2>
- <ul>
- </ul>
- </footer>
- </section>
+ <section>
+ <h2>Quaternion Time</h2>
+ <p>
+ I hate to start off the article like this. I really do. But it really wouldn't be a discussion of 3D simulation if we didn't jump right into quaternions. Before I start, however, I recommend you take a look at <a href='https://www.3dgep.com/understanding-quaternions'>this article</a>. Quaternions have been written about over and over throughout the years (and I have read many articles about them over and over throughout the years), so I will not waste your time describing every single detail here. The article that I linked to should provide you enough information to begin to understand what quaternions are and why they're important. That being said, I will provide a brief intro to quaternions here, as well as my own C++ implementation of their algebra. (This article is also quite useful: <a href='http://danceswithcode.net/engineeringnotes/quaternions/quaternions.html'>Dance's With Code Website</a>)
+ <br/><br/>
+
+ </p>
+ </section>
+ <section>
+ <h2>
+ Live Example
+ </h2>
+ <p>
+ <button id='force_apply'>Click Me</button>
+ </p>
+ <div class="opengl_canvas_container">
+ <canvas id="gl_canvas" width="800" height="600"></canvas>
+ <button id="gl_canvas_play" class="play_button">
+ Play
+ </button>
+ <button id="gl_canvas_stop" class="stop_button">
+ Stop
+ </button>
+ </div>
+
+ <footer id="references">
+ <h2>References</h2>
+ <ul>
+ </ul>
+ </footer>
+ </section>
</article>
</main>
</body>
diff --git a/3d/rigidbody.html.content b/3d/rigidbody.html.content
index 8bbf294..5a3eca2 100644
--- a/3d/rigidbody.html.content
+++ b/3d/rigidbody.html.content
@@ -17,24 +17,35 @@
<article>
<h1>Rigidbody in 3D</h1>
<section>
- <section>
- <h2>
- Live Example
- </h2>
- <div class="opengl_canvas_container">
- <canvas id="gl_canvas" width="800" height="600"></canvas>
- <button id="gl_canvas_play" class="play_button">
- Play
- </button>
- <button id="gl_canvas_stop" class="stop_button">
- Stop
- </button>
- </div>
-
- <footer id="references">
- <h2>References</h2>
- <ul>
- </ul>
- </footer>
- </section>
+ <section>
+ <h2>Quaternion Time</h2>
+ <p>
+ I hate to start off the article like this. I really do. But it really wouldn't be a discussion of 3D simulation if we didn't jump right into quaternions. Before I start, however, I recommend you take a look at <a href='https://www.3dgep.com/understanding-quaternions'>this article</a>. Quaternions have been written about over and over throughout the years (and I have read many articles about them over and over throughout the years), so I will not waste your time describing every single detail here. The article that I linked to should provide you enough information to begin to understand what quaternions are and why they're important. That being said, I will provide a brief intro to quaternions here, as well as my own C++ implementation of their algebra. (This article is also quite useful: <a href='http://danceswithcode.net/engineeringnotes/quaternions/quaternions.html'>Dance's With Code Website</a>)
+ <br/><br/>
+
+ </p>
+ </section>
+ <section>
+ <h2>
+ Live Example
+ </h2>
+ <p>
+ <button id='force_apply'>Click Me</button>
+ </p>
+ <div class="opengl_canvas_container">
+ <canvas id="gl_canvas" width="800" height="600"></canvas>
+ <button id="gl_canvas_play" class="play_button">
+ Play
+ </button>
+ <button id="gl_canvas_stop" class="stop_button">
+ Stop
+ </button>
+ </div>
+
+ <footer id="references">
+ <h2>References</h2>
+ <ul>
+ </ul>
+ </footer>
+ </section>
</article>
diff --git a/3d/rigidbody/dist/output.wasm b/3d/rigidbody/dist/output.wasm
index 98d25e5..8ebe0dd 100755
--- a/3d/rigidbody/dist/output.wasm
+++ b/3d/rigidbody/dist/output.wasm
Binary files differ
diff --git a/3d/rigidbody/main.cpp b/3d/rigidbody/main.cpp
index c83018b..90c6bc8 100644
--- a/3d/rigidbody/main.cpp
+++ b/3d/rigidbody/main.cpp
@@ -13,17 +13,96 @@
#include <cmath>
#include <cfloat>
+struct Impulse {
+ Vector3 force = { 0, 0, 0 };
+ Vector3 pointOfApplication = { 0, 0, 0 };
+ float32 timeOfApplicationSeconds = 0.016f;
+ float32 timeAppliedSeconds = 0.f;
+ bool isDead = false;
+};
+
+const int32 MAX_IMPULSES = 4;
+
struct Rigidbody3d {
+ int32 numImpulses = 0;
+ Impulse activeImpulses[MAX_IMPULSES];
Vector3 velocity;
Vector3 position;
+ float32 mass = 1.f;
+
+ Vector3 rotationalVelocity;
+ Quaternion rotation;
+ float32 momentOfInertia = 1.f;
+
+ void reset() {
+ numImpulses = 0;
+ velocity = { 0, 0, 0};
+ rotationalVelocity = { 0, 0, 0 };
+ }
+
+ void applyImpulse(Impulse i) {
+ if (numImpulses > MAX_IMPULSES) {
+ printf("Unable to apply impulse. Buffer full.\n");
+ return;
+ }
+
+ activeImpulses[numImpulses] = i;
+ numImpulses++;
+ }
+
+ void update(float32 deltaTimeSeconds) {
+ // Apply gravity
+ //velocity += (Vector3 { 0.f, -9.8f, 0.f } * deltaTimeSeconds);
+
+ Vector3 force = { 0.f, 0.f, 0.f };
+ Vector3 torque = { 0.f, 0.f, 0.f };
+ for (int32 idx = 0; idx < numImpulses; idx++) {
+ Impulse& i = activeImpulses[idx];
- void update(float32 dtSeconds) {
+ float32 nextTimeAppliedSeconds = i.timeAppliedSeconds + deltaTimeSeconds;
+ if (nextTimeAppliedSeconds >= i.timeOfApplicationSeconds) {
+ nextTimeAppliedSeconds = i.timeOfApplicationSeconds;
+ i.isDead = true;
+ }
+
+ float32 impulseDtSeconds = nextTimeAppliedSeconds - i.timeAppliedSeconds;
+ Vector3 forceToApply = i.force * (impulseDtSeconds / i.timeOfApplicationSeconds);
+ force += forceToApply;
+
+ force.printDebug("Force applied\n");
+
+ torque += i.pointOfApplication.cross(force).dot(forceToApply);
+ i.timeAppliedSeconds = nextTimeAppliedSeconds;
+ }
+ Vector3 acceleration = force / mass;
+ velocity += (acceleration * deltaTimeSeconds);
+ position += (velocity * deltaTimeSeconds);
+
+ Vector3 rotationalAcceleration = torque / momentOfInertia;
+ rotationalVelocity += (rotationalAcceleration * deltaTimeSeconds);
+
+ Quaternion rotationVelocityQuat = { 0, rotationalVelocity.x, rotationalVelocity.y, rotationalVelocity.z };
+ Quaternion dqDt = (rotationVelocityQuat * rotation) * 0.5f;
+ rotation = rotation + (dqDt * deltaTimeSeconds);
+
+ for (int32 idx = 0; idx < numImpulses; idx++) {
+ if (activeImpulses[idx].isDead) {
+ for (int j = idx + 1; j < numImpulses; j++) {
+ activeImpulses[j - 1] = activeImpulses[j];
+ }
+
+ idx = idx - 1;
+ numImpulses--;
+ }
+ }
}
};
struct Cube {
Mesh3d mesh;
+ Rigidbody3d body;
+ float32 scale = 10.f;
void load(Renderer3d* renderer) {
Vertex3d cubeVertices[] = {
@@ -87,12 +166,18 @@ struct Cube {
mesh.load(&cubeVertices[0], 8, cubeIndices, 36, renderer);
+
+ body.position = Vector3 { 0.f, 0.f, 0.f };
+ body.velocity = Vector3 { 0.f, 0.f, 0.f };
+ mesh.model = Mat4x4().scale(scale);
+
+ float32 singleFaceArea = scale * scale;
+ body.momentOfInertia = (body.mass * singleFaceArea) / 6.f;
}
void update(float32 dtSeconds) {
- float32 multiplier = (PI / 8.f) * dtSeconds;
- Vector3 currentRotation = Vector3 { multiplier, multiplier, multiplier };
- mesh.model = mesh.model.rotate(currentRotation.x, currentRotation.y, currentRotation.z);
+ body.update(dtSeconds);
+ mesh.model = mesh.model.translate(body.position) * body.rotation.toMatrix();
}
void render(Renderer3d* renderer) {
@@ -106,6 +191,7 @@ struct Cube {
EM_BOOL onPlayClicked(int eventType, const EmscriptenMouseEvent* mouseEvent, void* userData);
EM_BOOL onStopClicked(int eventType, const EmscriptenMouseEvent* mouseEvent, void* userData);
+EM_BOOL onForceApplicationRequested(int eventType, const EmscriptenMouseEvent* mouseEvent, void* userData);
void load();
void update(float32 time, void* userData);
@@ -122,14 +208,17 @@ int main() {
context.init("#gl_canvas");
emscripten_set_click_callback("#gl_canvas_play", NULL, false, onPlayClicked);
emscripten_set_click_callback("#gl_canvas_stop", NULL, false, onStopClicked);
+ emscripten_set_click_callback("#force_apply", NULL, false, onForceApplicationRequested);
return 0;
}
void load() {
renderer.load(&context);
+ cube.scale = 12.f;
+ cube.body.mass = 100.f;
cube.load(&renderer);
- camera.projection = Mat4x4().getPerspectiveProjection(0.1f, 100.f, PI / 2.f, 800.f / 600.f);
- camera.view = Mat4x4().translate({ 0, 0, -10 });
+ camera.projection = Mat4x4().getPerspectiveProjection(0.1f, 10000.f, DEG_TO_RAD(60.f), 800.f / 600.f);
+ camera.view = Mat4x4().translate({ 0, 0, -250 });
mainLoop.run(update);
}
@@ -162,3 +251,12 @@ EM_BOOL onStopClicked(int eventType, const EmscriptenMouseEvent* mouseEvent, voi
unload();
return true;
}
+
+EM_BOOL onForceApplicationRequested(int eventType, const EmscriptenMouseEvent* mouseEvent, void* userData) {
+ printf("Force applied\n");
+ Impulse base;
+ base.force = { 0, 1000, 0 };
+ base.pointOfApplication = { 0, 1, 0 };
+ cube.body.applyImpulse(base);
+ return true;
+}
diff --git a/resources.html.content b/resources.html.content
new file mode 100644
index 0000000..2b3aef1
--- /dev/null
+++ b/resources.html.content
@@ -0,0 +1,12 @@
+<article>
+ <h1>Resources</h1>
+ <section>
+ <p>Here are a set of books and resources that I have found particularly helpful in forming my understanding of physics engines. I highly recommend going through all of these resource.</p>
+ </section>
+ <section>
+ <h2>Mathematics</h2>
+ <ul>
+ <li><a href='http://canvas.projekti.info/ebooks/Mathematics%20for%203D%20Game%20Programming%20and%20Computer%20Graphics,%20Third%20Edition.pdf'>Mathematics for 3D Game Programming and Computer Graphics, Third Edition</a>: a great resource on foundational mathematics for computer graphics. I am linking to the free pdf version here so that you can test drive it, but I highly recommend having a physical copy of this book on your shelf. It is a simple and elegant reference for all things computer graphics.</li>
+ </ul>
+ </section>
+</article>
diff --git a/shared_cpp/mathlib.cpp b/shared_cpp/mathlib.cpp
index b7748fe..fb09cd9 100644
--- a/shared_cpp/mathlib.cpp
+++ b/shared_cpp/mathlib.cpp
@@ -155,6 +155,13 @@ Vector3 Vector3::operator+(const Vector3& v2) {
return add(v2);
}
+Vector3& Vector3::operator+=(Vector3 other) {
+ x += other.x;
+ y += other.y;
+ z += other.z;
+ return *this;
+}
+
Vector3 Vector3::operator-(const Vector3& v2) {
return subtract(v2);
}
@@ -167,6 +174,14 @@ Vector3 Vector3::operator*(float value) {
return scale(value);
}
+Vector3 Vector3::operator/(const Vector3& v2) {
+ return {
+ x / v2.x,
+ y / v2.y,
+ z / v2.z
+ };
+}
+
Vector3 Vector3::operator*(const Vector3& v2) {
return {
x * v2.x,
@@ -623,3 +638,16 @@ Mat4x4 Quaternion::toMatrix() const {
float Quaternion::dot(const Quaternion& other) const {
return w * other.w + x * other.x + y * other.y + z * other.z;
}
+
+Quaternion quaternionFromRotation(Vector3 axis, float angleRadians) {
+ float halfAngleRadians = angleRadians / 2.f;
+ float cosHalfAngRad = cosf(halfAngleRadians);
+ float sinHalfAngRad = sinf(halfAngleRadians);
+
+ return {
+ cosHalfAngRad,
+ axis.x * sinHalfAngRad,
+ axis.y * sinHalfAngRad,
+ axis.z * sinHalfAngRad
+ };
+}
diff --git a/shared_cpp/mathlib.h b/shared_cpp/mathlib.h
index d550e90..e3c6875 100644
--- a/shared_cpp/mathlib.h
+++ b/shared_cpp/mathlib.h
@@ -18,6 +18,8 @@
#define ABS(x) (x < 0 ? -x : x)
#define SIGN(x) (x < 0 ? -1 : 1)
#define PI 3.141592653589793238463
+#define DEG_TO_RAD(x) (x * (PI / 180.f))
+#define RAD_TO_DEG(x) (x * (180.f / PI))
struct Vector2 {
float x = 0;
@@ -58,10 +60,12 @@ struct Vector3 {
Vector3 normalize();
Vector3 operator+(const Vector3& v2);
+ Vector3& operator+=(Vector3 other);
Vector3 operator-(const Vector3& v2);
Vector3 operator-();
Vector3 operator*(float value);
Vector3 operator*(const Vector3& v2);
+ Vector3 operator/(const Vector3& v2);
float operator[](int index);
void printDebug(const char* name);
@@ -75,7 +79,7 @@ struct Vector4 {
Vector4();
Vector4(float value);
- Vector4(float inX = 0.f, float inY = 0.f, float inZ = 0.f, float inW = 1.f);
+ Vector4(float inX, float inY, float inZ, float inW);
Vector4 fromColor(float r, float g, float b, float a);
Vector4 toNormalizedColor();
@@ -126,10 +130,10 @@ struct Mat4x4 {
};
struct Quaternion {
+ float w = 0;
float x = 0;
float y = 0;
float z = 0;
- float w = 0;
float operator [](int index);
Quaternion operator*(const Quaternion& other) const;
@@ -142,3 +146,5 @@ struct Quaternion {
float length() const;
float dot(const Quaternion& other) const;
};
+
+Quaternion quaternionFromRotation(Vector3 axis, float angleRadians);