RavEngine
Loading...
Searching...
No Matches
CmScaling.h
1// Redistribution and use in source and binary forms, with or without
2// modification, are permitted provided that the following conditions
3// are met:
4// * Redistributions of source code must retain the above copyright
5// notice, this list of conditions and the following disclaimer.
6// * Redistributions in binary form must reproduce the above copyright
7// notice, this list of conditions and the following disclaimer in the
8// documentation and/or other materials provided with the distribution.
9// * Neither the name of NVIDIA CORPORATION nor the names of its
10// contributors may be used to endorse or promote products derived
11// from this software without specific prior written permission.
12//
13// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
14// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
17// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
21// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24//
25// Copyright (c) 2008-2022 NVIDIA Corporation. All rights reserved.
26// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved.
27// Copyright (c) 2001-2004 NovodeX AG. All rights reserved.
28
29#ifndef CM_SCALING_H
30#define CM_SCALING_H
31
32#include "foundation/PxBounds3.h"
33#include "foundation/PxMat33.h"
34#include "foundation/PxMathUtils.h"
35#include "foundation/PxMat34.h"
36#include "foundation/PxSIMDHelpers.h"
37#include "geometry/PxMeshScale.h"
38#include "CmUtils.h"
39
40namespace physx
41{
42namespace Cm
43{
44 // PT: same as PxMeshScale::toMat33() but faster
45 PX_FORCE_INLINE PxMat33 toMat33(const PxMeshScale& meshScale)
46 {
47 const PxMat33Padded rot(meshScale.rotation);
48
49 PxMat33 trans = rot.getTranspose();
50 trans.column0 *= meshScale.scale[0];
51 trans.column1 *= meshScale.scale[1];
52 trans.column2 *= meshScale.scale[2];
53 return trans * rot;
54 }
55
56 // class that can perform scaling fast. Relatively large size, generated from PxMeshScale on demand.
57 // CS: I've removed most usages of this class, because most of the time only one-way transform is needed.
58 // If you only need a temporary FastVertex2ShapeScaling, setup your transform as PxMat34Legacy and use
59 // normal matrix multiplication or a transform() overload to convert points and bounds between spaces.
61 {
62 public:
64 {
65 //no scaling by default:
66 vertex2ShapeSkew = PxMat33(PxIdentity);
67 shape2VertexSkew = PxMat33(PxIdentity);
68 mFlipNormal = false;
69 }
70
71 PX_INLINE explicit FastVertex2ShapeScaling(const PxMeshScale& scale)
72 {
73 init(scale);
74 }
75
76 PX_INLINE FastVertex2ShapeScaling(const PxVec3& scale, const PxQuat& rotation)
77 {
78 init(scale, rotation);
79 }
80
81 PX_INLINE void init(const PxMeshScale& scale)
82 {
83 init(scale.scale, scale.rotation);
84 }
85
86 PX_INLINE void setIdentity()
87 {
88 vertex2ShapeSkew = PxMat33(PxIdentity);
89 shape2VertexSkew = PxMat33(PxIdentity);
90 mFlipNormal = false;
91 }
92
93 PX_INLINE void init(const PxVec3& scale, const PxQuat& rotation)
94 {
95 // TODO: may want to optimize this for cases where we have uniform or axis aligned scaling!
96 // That would introduce branches and it's unclear to me whether that's faster than just doing the math.
97 // Lazy computation would be another option, at the cost of introducing even more branches.
98
99 const PxMat33Padded R(rotation);
100 vertex2ShapeSkew = R.getTranspose();
101 const PxMat33 diagonal = PxMat33::createDiagonal(scale);
102 vertex2ShapeSkew = vertex2ShapeSkew * diagonal;
103 vertex2ShapeSkew = vertex2ShapeSkew * R;
104
105 /*
106 The inverse, is, explicitly:
107 shape2VertexSkew.setTransposed(R);
108 shape2VertexSkew.multiplyDiagonal(PxVec3(1.0f/scale.x, 1.0f/scale.y, 1.0f/scale.z));
109 shape2VertexSkew *= R;
110
111 It may be competitive to compute the inverse -- though this has a branch in it:
112 */
113
114 shape2VertexSkew = vertex2ShapeSkew.getInverse();
115
116 mFlipNormal = ((scale.x * scale.y * scale.z) < 0.0f);
117 }
118
119 PX_FORCE_INLINE void flipNormal(PxVec3& v1, PxVec3& v2) const
120 {
121 if (mFlipNormal)
122 {
123 PxVec3 tmp = v1; v1 = v2; v2 = tmp;
124 }
125 }
126
127 PX_FORCE_INLINE PxVec3 operator* (const PxVec3& src) const
128 {
129 return vertex2ShapeSkew * src;
130 }
131
132 PX_FORCE_INLINE PxVec3 operator% (const PxVec3& src) const
133 {
134 return shape2VertexSkew * src;
135 }
136
137 PX_FORCE_INLINE const PxMat33& getVertex2ShapeSkew() const
138 {
139 return vertex2ShapeSkew;
140 }
141
142 PX_FORCE_INLINE const PxMat33& getShape2VertexSkew() const
143 {
144 return shape2VertexSkew;
145 }
146
147 PX_INLINE PxMat34 getVertex2WorldSkew(const PxMat34& shape2world) const
148 {
149 const PxMat34 vertex2worldSkew = shape2world * getVertex2ShapeSkew();
150 //vertex2worldSkew = shape2world * [vertex2shapeSkew, 0]
151 //[aR at] * [bR bt] = [aR * bR aR * bt + at] NOTE: order of operations important so it works when this ?= left ?= right.
152 return vertex2worldSkew;
153 }
154
155 PX_INLINE PxMat34 getWorld2VertexSkew(const PxMat34& shape2world) const
156 {
157 //world2vertexSkew = shape2vertex * invPQ(shape2world)
158 //[aR 0] * [bR' -bR'*bt] = [aR * bR' -aR * bR' * bt + 0]
159
160 const PxMat33 rotate( shape2world[0], shape2world[1], shape2world[2] );
161 const PxMat33 M = getShape2VertexSkew() * rotate.getTranspose();
162 return PxMat34(M[0], M[1], M[2], -M * shape2world[3]);
163 }
164
166 void transformQueryBounds(PxVec3& center, PxVec3& extents, PxMat33& basis) const
167 {
168 basis.column0 = shape2VertexSkew * (basis.column0 * extents.x);
169 basis.column1 = shape2VertexSkew * (basis.column1 * extents.y);
170 basis.column2 = shape2VertexSkew * (basis.column2 * extents.z);
171
172 center = shape2VertexSkew * center;
173 extents = PxOptimizeBoundingBox(basis);
174 }
175
176 void transformPlaneToShapeSpace(const PxVec3& nIn, const PxReal dIn, PxVec3& nOut, PxReal& dOut) const
177 {
178 const PxVec3 tmp = shape2VertexSkew.transformTranspose(nIn);
179 const PxReal denom = 1.0f / tmp.magnitude();
180 nOut = tmp * denom;
181 dOut = dIn * denom;
182 }
183
184 PX_FORCE_INLINE bool flipsNormal() const { return mFlipNormal; }
185
186 private:
187 PxMat33 vertex2ShapeSkew;
188 PxMat33 shape2VertexSkew;
189 bool mFlipNormal;
190 };
191
192 PX_FORCE_INLINE void getScaledVertices(PxVec3* v, const PxVec3& v0, const PxVec3& v1, const PxVec3& v2, bool idtMeshScale, const Cm::FastVertex2ShapeScaling& scaling)
193 {
194 if(idtMeshScale)
195 {
196 v[0] = v0;
197 v[1] = v1;
198 v[2] = v2;
199 }
200 else
201 {
202 const PxI32 winding = scaling.flipsNormal() ? 1 : 0;
203 v[0] = scaling * v0;
204 v[1+winding] = scaling * v1;
205 v[2-winding] = scaling * v2;
206 }
207 }
208
209} // namespace Cm
210
211
212PX_INLINE PxMat34 operator*(const PxTransform& transform, const PxMeshScale& scale)
213{
214 const PxMat33Padded tmp(transform.q);
215
216 return PxMat34(tmp * Cm::toMat33(scale), transform.p);
217}
218
219PX_INLINE PxMat34 operator*(const PxMeshScale& scale, const PxTransform& transform)
220{
221 const PxMat33 scaleMat = Cm::toMat33(scale);
222 const PxMat33Padded t(transform.q);
223 const PxMat33 r = scaleMat * t;
224 const PxVec3 p = scaleMat * transform.p;
225 return PxMat34(r, p);
226}
227
228PX_INLINE PxMat34 operator*(const PxMat34& transform, const PxMeshScale& scale)
229{
230 return PxMat34(transform.m * Cm::toMat33(scale), transform.p);
231}
232
233PX_INLINE PxMat34 operator*(const PxMeshScale& scale, const PxMat34& transform)
234{
235 const PxMat33 scaleMat = Cm::toMat33(scale);
236 return PxMat34(scaleMat * transform.m, scaleMat * transform.p);
237}
238
239}
240
241#endif
Definition CmScaling.h:61
void transformQueryBounds(PxVec3 &center, PxVec3 &extents, PxMat33 &basis) const
Transforms a shape space OBB to a vertex space OBB. All 3 params are in and out.
Definition CmScaling.h:166
A padded version of PxMat33, to safely load its data using SIMD.
Definition PxSIMDHelpers.h:41
PX_CUDA_CALLABLE static PX_INLINE const PxMat33T createDiagonal(const PxVec3T< float > &d)
Construct from diagonal, off-diagonals are zero.
Definition PxMat33.h:186
3x3 matrix class
Definition PxMat33.h:91
PX_CUDA_CALLABLE PX_INLINE const PxVec3 transformTranspose(const PxVec3 &other) const
Transform vector by matrix transpose, v' = M^t*v.
Definition PxMat33.h:332
PX_CUDA_CALLABLE PX_FORCE_INLINE const PxMat33 getTranspose() const
Get transposed matrix.
Definition PxMat33.h:190
PX_CUDA_CALLABLE PX_INLINE const PxMat33 getInverse() const
Get the real inverse.
Definition PxMat33.h:200
Definition PxMat34.h:50
A class expressing a nonuniform scaling transformation.
Definition PxMeshScale.h:69
This is a quaternion class. For more information on quaternion mathematics consult a mathematics sour...
Definition PxQuat.h:50
3 Element vector class.
Definition PxVec3.h:50
PX_CUDA_CALLABLE PX_FORCE_INLINE float magnitude() const
returns the magnitude
Definition PxVec3.h:183
#define PX_FORCE_INLINE
Definition PxPreprocessor.h:335
#define PX_INLINE
Definition PxPreprocessor.h:320
transform(pattern)
Definition docopt.py:72
Sorts an array of objects in ascending order, assuming that the predicate implements the < operator:
Definition PxBoxController.h:39
PX_INLINE void rotate(const Gu::Box &src, const PxMat34 &mtx, Gu::Box &obb)
recomputes the OBB after an arbitrary transform by a 4x4 matrix.
Definition GuBoxConversion.h:100
PX_FOUNDATION_API PxVec3 PxOptimizeBoundingBox(PxMat33 &basis)
computes a oriented bounding box around the scaled basis.
Definition FdMathUtils.cpp:140