88package com.facebook.react.uimanager
99
1010import com.facebook.infer.annotation.Assertions
11- import kotlin.math.abs
1211import kotlin.math.atan2
1312import kotlin.math.cos
1413import kotlin.math.sin
@@ -22,11 +21,7 @@ import kotlin.math.tan
2221public object MatrixMathHelper {
2322 private const val EPSILON = .00001
2423
25- private fun isZero (d : Double ): Boolean {
26- return if (java.lang.Double .isNaN(d)) {
27- false
28- } else abs(d) < EPSILON
29- }
24+ private fun isZero (d : Double ): Boolean = d > - EPSILON && d < EPSILON
3025
3126 @JvmStatic
3227 public fun multiplyInto (out : DoubleArray , a : DoubleArray , b : DoubleArray ) {
@@ -92,17 +87,16 @@ public object MatrixMathHelper {
9287 val translation = ctx.translation
9388 val rotationDegrees = ctx.rotationDegrees
9489
95- // create normalized, 2d array matrix
96- // and normalized 1d array perspectiveMatrix with redefined 4th column
9790 if (isZero(transformMatrix[15 ])) {
9891 return
9992 }
100- val matrix = Array (4 ) { DoubleArray (4 ) }
93+
94+ val normalizedMatrix = DoubleArray (16 )
10195 val perspectiveMatrix = DoubleArray (16 )
10296 for (i in 0 .. 3 ) {
10397 for (j in 0 .. 3 ) {
10498 val value = transformMatrix[i * 4 + j] / transformMatrix[15 ]
105- matrix[i][ j] = value
99+ normalizedMatrix[i * 4 + j] = value
106100 perspectiveMatrix[i * 4 + j] = if (j == 3 ) 0.0 else value
107101 }
108102 }
@@ -114,10 +108,19 @@ public object MatrixMathHelper {
114108 }
115109
116110 // isolate perspective
117- if (! isZero(matrix[0 ][3 ]) || ! isZero(matrix[1 ][3 ]) || ! isZero(matrix[2 ][3 ])) {
111+ if (
112+ ! isZero(normalizedMatrix[3 ]) ||
113+ ! isZero(normalizedMatrix[7 ]) ||
114+ ! isZero(normalizedMatrix[11 ])
115+ ) {
118116 // rightHandSide is the right hand side of the equation.
119117 // rightHandSide is a vector, or point in 3d space relative to the origin.
120- val rightHandSide = doubleArrayOf(matrix[0 ][3 ], matrix[1 ][3 ], matrix[2 ][3 ], matrix[3 ][3 ])
118+ val rightHandSide = doubleArrayOf(
119+ normalizedMatrix[3 ],
120+ normalizedMatrix[7 ],
121+ normalizedMatrix[11 ],
122+ normalizedMatrix[15 ],
123+ )
121124
122125 // Solve the equation by inverting perspectiveMatrix and multiplying
123126 // rightHandSide by the inverse.
@@ -126,50 +129,51 @@ public object MatrixMathHelper {
126129 multiplyVectorByMatrix(rightHandSide, transposedInversePerspectiveMatrix, perspective)
127130 } else {
128131 // no perspective
132+ perspective[0 ] = 0.0
133+ perspective[1 ] = 0.0
129134 perspective[2 ] = 0.0
130- perspective[1 ] = perspective[2 ]
131- perspective[0 ] = perspective[1 ]
132135 perspective[3 ] = 1.0
133136 }
134137
135- // translation is simple
136- for (i in 0 .. 2 ) {
137- translation[i] = matrix[3 ][i]
138- }
138+ translation[0 ] = normalizedMatrix[12 ]
139+ translation[1 ] = normalizedMatrix[13 ]
140+ translation[2 ] = normalizedMatrix[14 ]
139141
140142 // Now get scale and shear.
141143 // 'row' is a 3 element array of 3 component vectors
142144 val row = Array (3 ) { DoubleArray (3 ) }
143145 for (i in 0 .. 2 ) {
144- row[i][0 ] = matrix[i][ 0 ]
145- row[i][1 ] = matrix[i][ 1 ]
146- row[i][2 ] = matrix[i][ 2 ]
146+ row[i][0 ] = normalizedMatrix[i * 4 ]
147+ row[i][1 ] = normalizedMatrix[i * 4 + 1 ]
148+ row[i][2 ] = normalizedMatrix[i * 4 + 2 ]
147149 }
148150
149151 // Compute X scale factor and normalize first row.
150152 scale[0 ] = v3Length(row[0 ])
151- row[ 0 ] = v3Normalize (row[0 ], scale[0 ])
153+ v3NormalizeInPlace (row[0 ], scale[0 ])
152154
153155 // Compute XY shear factor and make 2nd row orthogonal to 1st.
154156 skew[0 ] = v3Dot(row[0 ], row[1 ])
155- row[ 1 ] = v3Combine (row[1 ], row[0 ], 1.0 , - skew[0 ])
157+ v3CombineInPlace (row[1 ], row[0 ], 1.0 , - skew[0 ])
156158
157159 // Now, compute Y scale and normalize 2nd row.
158- scale[1 ] = v3Length(row[1 ])
159- row[1 ] = v3Normalize(row[1 ], scale[1 ])
160- skew[0 ] / = scale[1 ]
160+ val scaleY = v3Length(row[1 ])
161+ scale[1 ] = scaleY
162+ v3NormalizeInPlace(row[1 ], scaleY)
163+ skew[0 ] / = scaleY
161164
162165 // Compute XZ and YZ shears, orthogonalize 3rd row
163166 skew[1 ] = v3Dot(row[0 ], row[2 ])
164- row[ 2 ] = v3Combine (row[2 ], row[0 ], 1.0 , - skew[1 ])
167+ v3CombineInPlace (row[2 ], row[0 ], 1.0 , - skew[1 ])
165168 skew[2 ] = v3Dot(row[1 ], row[2 ])
166- row[ 2 ] = v3Combine (row[2 ], row[1 ], 1.0 , - skew[2 ])
169+ v3CombineInPlace (row[2 ], row[1 ], 1.0 , - skew[2 ])
167170
168171 // Next, get Z scale and normalize 3rd row.
169- scale[2 ] = v3Length(row[2 ])
170- row[2 ] = v3Normalize(row[2 ], scale[2 ])
171- skew[1 ] / = scale[2 ]
172- skew[2 ] / = scale[2 ]
172+ val scaleZ = v3Length(row[2 ])
173+ scale[2 ] = scaleZ
174+ v3NormalizeInPlace(row[2 ], scaleZ)
175+ skew[1 ] / = scaleZ
176+ skew[2 ] / = scaleZ
173177
174178 // At this point, the matrix (in rows) is orthonormal.
175179 // Check for a coordinate system flip. If the determinant
@@ -340,6 +344,13 @@ public object MatrixMathHelper {
340344 return doubleArrayOf(vector[0 ] * im, vector[1 ] * im, vector[2 ] * im)
341345 }
342346
347+ private fun v3NormalizeInPlace (vector : DoubleArray , norm : Double ) {
348+ val inverseMagnitude = 1.0 / norm
349+ vector[0 ] * = inverseMagnitude
350+ vector[1 ] * = inverseMagnitude
351+ vector[2 ] * = inverseMagnitude
352+ }
353+
343354 /* *
344355 * The dot product of a and b, two 3-element vectors. From:
345356 * https://code.google.com/p/webgl-mjs/source/browse/mjs.js
@@ -367,6 +378,17 @@ public object MatrixMathHelper {
367378 )
368379 }
369380
381+ private fun v3CombineInPlace (
382+ a : DoubleArray ,
383+ b : DoubleArray ,
384+ aScale : Double ,
385+ bScale : Double ,
386+ ) {
387+ a[0 ] = aScale * a[0 ] + bScale * b[0 ]
388+ a[1 ] = aScale * a[1 ] + bScale * b[1 ]
389+ a[2 ] = aScale * a[2 ] + bScale * b[2 ]
390+ }
391+
370392 /* *
371393 * From:
372394 * http://www.opensource.apple.com/source/WebCore/WebCore-514/platform/graphics/transforms/TransformationMatrix.cpp
0 commit comments