1+ /*
2+ Open Asset Import Library (assimp)
3+ ----------------------------------------------------------------------
4+
5+ Copyright (c) 2006-2018, assimp team
6+
7+
8+ All rights reserved.
9+
10+ Redistribution and use of this software in source and binary forms,
11+ with or without modification, are permitted provided that the
12+ following conditions are met:
13+
14+ * Redistributions of source code must retain the above
15+ copyright notice, this list of conditions and the
16+ following disclaimer.
17+
18+ * Redistributions in binary form must reproduce the above
19+ copyright notice, this list of conditions and the
20+ following disclaimer in the documentation and/or other
21+ materials provided with the distribution.
22+
23+ * Neither the name of the assimp team, nor the names of its
24+ contributors may be used to endorse or promote products
25+ derived from this software without specific prior
26+ written permission of the assimp team.
27+
28+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
29+ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
30+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
31+ A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
32+ OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
33+ SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
34+ LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
35+ DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
36+ THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
37+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
38+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
39+
40+ ----------------------------------------------------------------------
41+ */
42+
43+ /* * @file PolyTools.h, various utilities for our dealings with arbitrary polygons */
44+
45+ package assimp
46+
47+ import glm_.vec2.Vec2
48+ import glm_.vec3.Vec3
49+
50+
51+ /* * Compute the signed area of a triangle. */
52+ inline fun getArea2D (v1 : Vec3 , v2 : Vec3 , v3 : Vec3 ): Double {
53+ return 0.5 * (v1.x * (v3.y - v2.y) + v2.x * (v1.y - v3.y) + v3.x * (v2.y - v1.y))
54+ }
55+
56+ /* * Compute the signed area of a triangle. */
57+ inline fun getArea2D (v1 : Vec2 , v2 : Vec2 , v3 : Vec2 ): Double {
58+ return 0.5 * (v1.x * (v3.y - v2.y) + v2.x * (v1.y - v3.y) + v3.x * (v2.y - v1.y))
59+ }
60+
61+ /* * Test if a given point p2 is on the left side of the line formed by p0-p1. */
62+ inline fun onLeftSideOfLine2D (p0 : Vec3 , p1 : Vec3 , p2 : Vec3 ): Boolean {
63+ return getArea2D(p0, p2, p1) > 0
64+ }
65+
66+ /* * Test if a given point p2 is on the left side of the line formed by p0-p1. */
67+ inline fun onLeftSideOfLine2D (p0 : Vec2 , p1 : Vec2 , p2 : Vec2 ): Boolean {
68+ return getArea2D(p0, p2, p1) > 0
69+ }
70+
71+ /* * Test if a given point is inside a given triangle in R2. */
72+ inline fun pointInTriangle2D (p0 : Vec3 , p1 : Vec3 , p2 : Vec3 , pp : Vec3 ): Boolean {
73+ // Point in triangle test using baryzentric coordinates
74+ val v0 = p1 - p0
75+ val v1 = p2 - p0
76+ val v2 = pp - p0
77+
78+ var dot00 = v0 dot v0
79+ val dot01 = v0 dot v1
80+ val dot02 = v0 dot v2
81+ var dot11 = v1 dot v1
82+ val dot12 = v1 dot v2
83+
84+ val invDenom = 1 / (dot00 * dot11 - dot01 * dot01)
85+ dot11 = (dot11 * dot02 - dot01 * dot12) * invDenom
86+ dot00 = (dot00 * dot12 - dot01 * dot02) * invDenom
87+
88+ return dot11 > 0 && dot00 > 0 && (dot11 + dot00 < 1 )
89+ }
90+
91+ /* * Test if a given point is inside a given triangle in R2. */
92+ inline fun pointInTriangle2D (p0 : Vec2 , p1 : Vec2 , p2 : Vec2 , pp : Vec2 ): Boolean {
93+ // Point in triangle test using baryzentric coordinates
94+ val v0 = p1 - p0
95+ val v1 = p2 - p0
96+ val v2 = pp - p0
97+
98+ var dot00 = v0 dot v0
99+ val dot01 = v0 dot v1
100+ val dot02 = v0 dot v2
101+ var dot11 = v1 dot v1
102+ val dot12 = v1 dot v2
103+
104+ val invDenom = 1 / (dot00 * dot11 - dot01 * dot01)
105+ dot11 = (dot11 * dot02 - dot01 * dot12) * invDenom
106+ dot00 = (dot00 * dot12 - dot01 * dot02) * invDenom
107+
108+ return dot11 > 0 && dot00 > 0 && (dot11 + dot00 < 1 )
109+ }
110+
111+
112+ /* * Check whether the winding order of a given polygon is counter-clockwise.
113+ * The function accepts an unconstrained template parameter, but is intended
114+ * to be used only with aiVector2D and aiVector3D (z axis is ignored, only
115+ * x and y are taken into account).
116+ * @note Code taken from http://cgm.cs.mcgill.ca/~godfried/teaching/cg-projects/97/Ian/applet1.html and translated to C++ */
117+ // template <typename T>
118+ // inline bool IsCCW(T* in , size_t npoints) {
119+ // double aa, bb, cc, b, c, theta
120+ // double convex_turn
121+ // double convex_sum = 0
122+ //
123+ // ai_assert(npoints >= 3)
124+ //
125+ // for (size_t i = 0; i < npoints - 2; i++) {
126+ // aa = (( in [i + 2].x - in[i].x) * ( in [i + 2].x - in[i].x))+
127+ // ((-in[i + 2].y + in[i].y) * (-in[i + 2].y + in[i].y))
128+ //
129+ // bb = (( in [i + 1].x - in[i].x) * ( in [i + 1].x - in[i].x))+
130+ // ((-in[i + 1].y + in[i].y) * (-in[i + 1].y + in[i].y))
131+ //
132+ // cc = (( in [i + 2].x - in[i + 1].x) *
133+ // ( in [i + 2].x - in[i + 1].x))+
134+ // ((-in[i + 2].y + in[i + 1].y) *
135+ // (-in[i + 2].y + in[i + 1].y))
136+ //
137+ // b = std::sqrt(bb)
138+ // c = std::sqrt(cc)
139+ // theta = std::acos((bb + cc - aa) / (2 * b * c))
140+ //
141+ // if (OnLeftSideOfLine2D(in[i], in [i+2], in [i+1])) {
142+ // // if (convex(in[i].x, in[i].y,
143+ // // in[i+1].x, in[i+1].y,
144+ // // in[i+2].x, in[i+2].y)) {
145+ // convex_turn = AI_MATH_PI_F - theta
146+ // convex_sum += convex_turn
147+ // }
148+ // else {
149+ // convex_sum -= AI_MATH_PI_F - theta
150+ // }
151+ // }
152+ // aa = (( in [1].x - in[npoints - 2].x) *
153+ // ( in [1].x - in[npoints - 2].x))+
154+ // ((-in[1].y + in[npoints - 2].y) *
155+ // (-in[1].y + in[npoints - 2].y))
156+ //
157+ // bb = (( in [0].x - in[npoints - 2].x) *
158+ // ( in [0].x - in[npoints - 2].x))+
159+ // ((-in[0].y + in[npoints - 2].y) *
160+ // (-in[0].y + in[npoints - 2].y))
161+ //
162+ // cc = (( in [1].x - in[0].x) * ( in [1].x - in[0].x))+
163+ // ((-in[1].y + in[0].y) * (-in[1].y + in[0].y))
164+ //
165+ // b = std::sqrt(bb)
166+ // c = std::sqrt(cc)
167+ // theta = std::acos((bb + cc - aa) / (2 * b * c))
168+ //
169+ // //if (convex(in[npoints-2].x, in[npoints-2].y,
170+ // // in[0].x, in[0].y,
171+ // // in[1].x, in[1].y)) {
172+ // if (OnLeftSideOfLine2D(in[npoints - 2], in [1], in [0])) {
173+ // convex_turn = AI_MATH_PI_F - theta
174+ // convex_sum += convex_turn
175+ // }
176+ // else {
177+ // convex_sum -= AI_MATH_PI_F - theta
178+ // }
179+ //
180+ // return convex_sum >= (2 * AI_MATH_PI_F)
181+ // }
182+
183+
184+ /* * Compute the normal of an arbitrary polygon in R3.
185+ *
186+ * The code is based on Newell's formula, that is a polygons normal is the ratio
187+ * of its area when projected onto the three coordinate axes.
188+ *
189+ * @param out Receives the output normal
190+ * @param num Number of input vertices
191+ * @param x X data source. x[ofs_x*n] is the n'th element.
192+ * @param y Y data source. y[ofs_y*n] is the y'th element
193+ * @param z Z data source. z[ofs_z*n] is the z'th element
194+ *
195+ * @note The data arrays must have storage for at least num+2 elements. Using
196+ * this method is much faster than the 'other' NewellNormal()
197+ */
198+ fun newellNormal (out : Vec3 , num : Int , vecs : Array <Vec3 >) {
199+ // Duplicate the first two vertices at the end
200+ vecs[num + 0 ](vecs[0 ])
201+ vecs[num + 1 ](vecs[1 ])
202+
203+ var sumXy = 0f
204+ var sumYz = 0f
205+ var sumZx = 0f
206+
207+ var ptr = 1
208+ var low = 0
209+ var high = 2
210+
211+ repeat(num) {
212+ sumXy + = vecs[ptr].x * (vecs[high].y- vecs[low].y)
213+ sumYz + = vecs[ptr].y * (vecs[high].z- vecs[low].z)
214+ sumZx + = vecs[ptr].z * (vecs[high].x- vecs[low].x)
215+
216+ ptr++
217+ low++
218+ high++
219+ }
220+ out (sumYz, sumZx, sumXy)
221+ }
0 commit comments