Skip to content

Commit 1c2d974

Browse files
committed
triangulate
1 parent 2ba2dbb commit 1c2d974

File tree

5 files changed

+754
-422
lines changed

5 files changed

+754
-422
lines changed

build.gradle

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ dependencies {
3535

3636
implementation 'com.github.kotlin-graphics:uno-sdk:f97f9853e6158a86550268b63ad2800e0e08737f'
3737

38-
testCompile 'io.kotlintest:kotlintest-runner-junit5:3.0.4'
38+
testCompile 'io.kotlintest:kotlintest-runner-junit5:3.0.6'
3939

4040
implementation 'io.github.microutils:kotlin-logging:1.4.6'
4141

Lines changed: 221 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,221 @@
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+
}

src/main/kotlin/assimp/mesh.kt

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -105,7 +105,7 @@ data class AiBone(
105105
}
106106
}
107107

108-
// ---------------------------------------------------------------------------
108+
typealias AiPrimitiveTypeMask = Int
109109
/** @brief Enumerates the types of geometric primitives supported by Assimp.
110110
* 1 1
111111
* @see aiFace Face data structure
@@ -142,6 +142,7 @@ enum class AiPrimitiveType(val i: Int) {
142142
}
143143
}
144144

145+
infix fun AiPrimitiveType.or(other: AiPrimitiveType) = i or other.i
145146
infix fun Int.or(other: AiPrimitiveType) = or(other.i)
146147
infix fun Int.wo(other: AiPrimitiveType) = and(other.i.inv())
147148
infix fun Int.has(other: AiPrimitiveType) = and(other.i) != 0
@@ -189,7 +190,7 @@ open class AiMesh(
189190
/** Bitwise combination of the members of the #aiPrimitiveType enum.
190191
* This specifies which types of primitives are present in the mesh.
191192
* The "SortByPrimitiveType"-Step can be used to make sure the output meshes consist of one primitive Type each. */
192-
var primitiveTypes: Int = 0,
193+
var primitiveTypes: AiPrimitiveTypeMask = 0,
193194

194195
/** The number of vertices in this mesh.
195196
* This is also the size of all of the per-vertex data arrays.

0 commit comments

Comments
 (0)