Skip to content

Commit 7dfaed2

Browse files
leifericfclaude
andcommitted
Unify rotate-x/y/z into single rotate function with axis keyword
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
1 parent 7a194a4 commit 7dfaed2

3 files changed

Lines changed: 43 additions & 66 deletions

File tree

src/eido/math.clj

Lines changed: 16 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -61,32 +61,21 @@
6161

6262
;; --- rotations ---
6363

64-
(defn rotate-x
65-
"Rotates a point around the X axis by angle (radians)."
66-
[[x y z] angle]
64+
(defn rotate
65+
"Rotates a point around the given axis (:x, :y, or :z) by angle (radians)."
66+
[[x y z] axis angle]
6767
(let [c (Math/cos angle)
6868
s (Math/sin angle)]
69-
[(double x)
70-
(- (* (double y) c) (* (double z) s))
71-
(+ (* (double y) s) (* (double z) c))]))
72-
73-
(defn rotate-y
74-
"Rotates a point around the Y axis by angle (radians)."
75-
[[x y z] angle]
76-
(let [c (Math/cos angle)
77-
s (Math/sin angle)]
78-
[(+ (* (double x) c) (* (double z) s))
79-
(double y)
80-
(- (* (double z) c) (* (double x) s))]))
81-
82-
(defn rotate-z
83-
"Rotates a point around the Z axis by angle (radians)."
84-
[[x y z] angle]
85-
(let [c (Math/cos angle)
86-
s (Math/sin angle)]
87-
[(- (* (double x) c) (* (double y) s))
88-
(+ (* (double x) s) (* (double y) c))
89-
(double z)]))
69+
(case axis
70+
:x [(double x)
71+
(- (* (double y) c) (* (double z) s))
72+
(+ (* (double y) s) (* (double z) c))]
73+
:y [(+ (* (double x) c) (* (double z) s))
74+
(double y)
75+
(- (* (double z) c) (* (double x) s))]
76+
:z [(- (* (double x) c) (* (double y) s))
77+
(+ (* (double x) s) (* (double y) c))
78+
(double z)])))
9079

9180
;; --- projection ---
9281

@@ -122,9 +111,9 @@
122111
pitch (get projection :projection/pitch 0.0)
123112
roll (get projection :projection/roll 0.0)]
124113
(-> point
125-
(rotate-y (- yaw))
126-
(rotate-x (- pitch))
127-
(rotate-z (- roll)))))
114+
(rotate :y (- yaw))
115+
(rotate :x (- pitch))
116+
(rotate :z (- roll)))))
128117

129118
(defn make-projector
130119
"Returns a function that projects 3D points to 2D screen coordinates.

src/eido/scene3d/transform.clj

Lines changed: 14 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -16,27 +16,20 @@
1616
(assoc face :face/vertices new-verts)))
1717
mesh))
1818

19-
(defn- rotate-fn [axis]
20-
(case axis
21-
:x m/rotate-x
22-
:y m/rotate-y
23-
:z m/rotate-z))
24-
2519
(defn rotate-mesh
2620
"Rotates all vertices and normals in a mesh around the given axis.
2721
axis: :x, :y, or :z. angle: radians."
2822
[mesh axis angle]
29-
(let [rot (rotate-fn axis)]
30-
(mapv (fn [face]
31-
(let [new-verts (mapv #(rot % angle) (:face/vertices face))
32-
new-normal (rot (:face/normal face) angle)]
33-
(cond-> (assoc face
34-
:face/vertices new-verts
35-
:face/normal new-normal)
36-
(:face/vertex-normals face)
37-
(assoc :face/vertex-normals
38-
(mapv #(rot % angle) (:face/vertex-normals face))))))
39-
mesh)))
23+
(mapv (fn [face]
24+
(let [new-verts (mapv #(m/rotate % axis angle) (:face/vertices face))
25+
new-normal (m/rotate (:face/normal face) axis angle)]
26+
(cond-> (assoc face
27+
:face/vertices new-verts
28+
:face/normal new-normal)
29+
(:face/vertex-normals face)
30+
(assoc :face/vertex-normals
31+
(mapv #(m/rotate % axis angle) (:face/vertex-normals face))))))
32+
mesh))
4033

4134
(defn scale-mesh
4235
"Scales all vertices in a mesh. factor is a number (uniform) or [sx sy sz]."
@@ -70,9 +63,8 @@
7063
(let [pos (u/axis-component axis vertex)
7164
range (- (double ax-max) (double ax-min))
7265
t (if (zero? range) 0.0 (/ (- pos (double ax-min)) range))
73-
angle (* (double amount) t)
74-
rot (case axis :x m/rotate-x :y m/rotate-y :z m/rotate-z)]
75-
(rot vertex angle)))
66+
angle (* (double amount) t)]
67+
(m/rotate vertex axis angle)))
7668

7769
(defn- deform-taper
7870
"Scales the cross-section perpendicular to axis by position along it."
@@ -95,8 +87,8 @@
9587
t (if (zero? range) 0.0 (/ (- pos (double ax-min)) range))
9688
angle (* (double amount) t)
9789
;; Bend around perpendicular axis: Y bends around Z, X around Y, Z around X
98-
rot (case axis :x m/rotate-y :y m/rotate-z :z m/rotate-x)]
99-
(rot vertex angle)))
90+
bend-axis (case axis :x :y :y :z :z :x)]
91+
(m/rotate vertex bend-axis angle)))
10092

10193
(defn- deform-inflate
10294
"Pushes each vertex along its face normal by a fixed amount."

test/eido/math_test.clj

Lines changed: 13 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -50,26 +50,22 @@
5050

5151
;; --- rotations ---
5252

53-
(deftest rotate-x-test
54-
(testing "90 degrees rotates Y to Z"
55-
(let [result (m/rotate-x [0 1 0] (/ Math/PI 2))]
53+
(deftest rotate-test
54+
(testing "X: 90 degrees rotates Y to Z"
55+
(let [result (m/rotate [0 1 0] :x (/ Math/PI 2))]
5656
(is (approx= [0.0 0.0 1.0] result))))
57-
(testing "identity rotation"
58-
(is (approx= [1.0 2.0 3.0] (m/rotate-x [1 2 3] 0)))))
59-
60-
(deftest rotate-y-test
61-
(testing "90 degrees rotates Z to X"
62-
(let [result (m/rotate-y [0 0 1] (/ Math/PI 2))]
57+
(testing "X: identity rotation"
58+
(is (approx= [1.0 2.0 3.0] (m/rotate [1 2 3] :x 0))))
59+
(testing "Y: 90 degrees rotates Z to X"
60+
(let [result (m/rotate [0 0 1] :y (/ Math/PI 2))]
6361
(is (approx= [1.0 0.0 0.0] result))))
64-
(testing "identity rotation"
65-
(is (approx= [1.0 2.0 3.0] (m/rotate-y [1 2 3] 0)))))
66-
67-
(deftest rotate-z-test
68-
(testing "90 degrees rotates X to Y"
69-
(let [result (m/rotate-z [1 0 0] (/ Math/PI 2))]
62+
(testing "Y: identity rotation"
63+
(is (approx= [1.0 2.0 3.0] (m/rotate [1 2 3] :y 0))))
64+
(testing "Z: 90 degrees rotates X to Y"
65+
(let [result (m/rotate [1 0 0] :z (/ Math/PI 2))]
7066
(is (approx= [0.0 1.0 0.0] result))))
71-
(testing "identity rotation"
72-
(is (approx= [1.0 2.0 3.0] (m/rotate-z [1 2 3] 0)))))
67+
(testing "Z: identity rotation"
68+
(is (approx= [1.0 2.0 3.0] (m/rotate [1 2 3] :z 0)))))
7369

7470
;; --- projections ---
7571

0 commit comments

Comments
 (0)