123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217 |
- /*
- Open Asset Import Library (assimp)
- ----------------------------------------------------------------------
- Copyright (c) 2006-2024, assimp team
- All rights reserved.
- Redistribution and use of this software in source and binary forms,
- with or without modification, are permitted provided that the
- following conditions are met:
- * Redistributions of source code must retain the above
- copyright notice, this list of conditions and the
- following disclaimer.
- * Redistributions in binary form must reproduce the above
- copyright notice, this list of conditions and the
- following disclaimer in the documentation and/or other
- materials provided with the distribution.
- * Neither the name of the assimp team, nor the names of its
- contributors may be used to endorse or promote products
- derived from this software without specific prior
- written permission of the assimp team.
- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- ----------------------------------------------------------------------
- */
- /** @file PolyTools.h, various utilities for our dealings with arbitrary polygons */
- #pragma once
- #ifndef AI_POLYTOOLS_H_INCLUDED
- #define AI_POLYTOOLS_H_INCLUDED
- #include <assimp/material.h>
- #include <assimp/ai_assert.h>
- namespace Assimp {
- // -------------------------------------------------------------------------------
- /** Compute the signed area of a triangle.
- * The function accepts an unconstrained template parameter for use with
- * both aiVector3D and aiVector2D, but generally ignores the third coordinate.*/
- template <typename T>
- inline double GetArea2D(const T& v1, const T& v2, const T& v3) {
- return 0.5 * (v1.x * ((double)v3.y - v2.y) + v2.x * ((double)v1.y - v3.y) + v3.x * ((double)v2.y - v1.y));
- }
- // -------------------------------------------------------------------------------
- /** Test if a given point p2 is on the left side of the line formed by p0-p1.
- * The function accepts an unconstrained template parameter for use with
- * both aiVector3D and aiVector2D, but generally ignores the third coordinate.*/
- template <typename T>
- inline int OnLeftSideOfLine2D(const T& p0, const T& p1,const T& p2) {
- double area = GetArea2D(p0,p2,p1);
- if(std::abs(area) < ai_epsilon)
- return 0;
- else if(area > 0)
- return 1;
- else
- return -1;
- }
- // -------------------------------------------------------------------------------
- /** Test if a given point is inside a given triangle in R2.
- * The function accepts an unconstrained template parameter for use with
- * both aiVector3D and aiVector2D, but generally ignores the third coordinate.*/
- template <typename T>
- inline bool PointInTriangle2D(const T& p0, const T& p1,const T& p2, const T& pp) {
- // pp should be left side of the three triangle side, by ccw arrow
- int c1 = OnLeftSideOfLine2D(p0, p1, pp);
- int c2 = OnLeftSideOfLine2D(p1, p2, pp);
- int c3 = OnLeftSideOfLine2D(p2, p0, pp);
- return (c1 >= 0) && (c2 >= 0) && (c3 >= 0);
- }
- // -------------------------------------------------------------------------------
- /** Check whether the winding order of a given polygon is counter-clockwise.
- * The function accepts an unconstrained template parameter, but is intended
- * to be used only with aiVector2D and aiVector3D (z axis is ignored, only
- * x and y are taken into account).
- * @note Code taken from http://cgm.cs.mcgill.ca/~godfried/teaching/cg-projects/97/Ian/applet1.html and translated to C++
- */
- template <typename T>
- inline bool IsCCW(T* in, size_t npoints) {
- double aa, bb, cc, b, c, theta;
- double convex_turn;
- double convex_sum = 0;
- ai_assert(npoints >= 3);
- for (size_t i = 0; i < npoints - 2; i++) {
- aa = ((in[i+2].x - in[i].x) * (in[i+2].x - in[i].x)) +
- ((-in[i+2].y + in[i].y) * (-in[i+2].y + in[i].y));
- bb = ((in[i+1].x - in[i].x) * (in[i+1].x - in[i].x)) +
- ((-in[i+1].y + in[i].y) * (-in[i+1].y + in[i].y));
- cc = ((in[i+2].x - in[i+1].x) *
- (in[i+2].x - in[i+1].x)) +
- ((-in[i+2].y + in[i+1].y) *
- (-in[i+2].y + in[i+1].y));
- b = std::sqrt(bb);
- c = std::sqrt(cc);
- theta = std::acos((bb + cc - aa) / (2 * b * c));
- if (OnLeftSideOfLine2D(in[i],in[i+2],in[i+1]) == 1) {
- // if (convex(in[i].x, in[i].y,
- // in[i+1].x, in[i+1].y,
- // in[i+2].x, in[i+2].y)) {
- convex_turn = AI_MATH_PI_F - theta;
- convex_sum += convex_turn;
- } else {
- convex_sum -= AI_MATH_PI_F - theta;
- }
- }
- aa = ((in[1].x - in[npoints-2].x) *
- (in[1].x - in[npoints-2].x)) +
- ((-in[1].y + in[npoints-2].y) *
- (-in[1].y + in[npoints-2].y));
- bb = ((in[0].x - in[npoints-2].x) *
- (in[0].x - in[npoints-2].x)) +
- ((-in[0].y + in[npoints-2].y) *
- (-in[0].y + in[npoints-2].y));
- cc = ((in[1].x - in[0].x) * (in[1].x - in[0].x)) +
- ((-in[1].y + in[0].y) * (-in[1].y + in[0].y));
- b = std::sqrt(bb);
- c = std::sqrt(cc);
- theta = std::acos((bb + cc - aa) / (2 * b * c));
- //if (convex(in[npoints-2].x, in[npoints-2].y,
- // in[0].x, in[0].y,
- // in[1].x, in[1].y)) {
- if (OnLeftSideOfLine2D(in[npoints-2],in[1],in[0]) == 1) {
- convex_turn = AI_MATH_PI_F - theta;
- convex_sum += convex_turn;
- } else {
- convex_sum -= AI_MATH_PI_F - theta;
- }
- return convex_sum >= (2 * AI_MATH_PI_F);
- }
- // -------------------------------------------------------------------------------
- /** Compute the normal of an arbitrary polygon in R3.
- *
- * The code is based on Newell's formula, that is a polygons normal is the ratio
- * of its area when projected onto the three coordinate axes.
- *
- * @param out Receives the output normal
- * @param num Number of input vertices
- * @param x X data source. x[ofs_x*n] is the n'th element.
- * @param y Y data source. y[ofs_y*n] is the y'th element
- * @param z Z data source. z[ofs_z*n] is the z'th element
- *
- * @note The data arrays must have storage for at least num+2 elements. Using
- * this method is much faster than the 'other' NewellNormal()
- */
- template <int ofs_x, int ofs_y, int ofs_z, typename TReal>
- inline void NewellNormal (aiVector3t<TReal>& out, int num, TReal* x, TReal* y, TReal* z) {
- // Duplicate the first two vertices at the end
- x[(num+0)*ofs_x] = x[0];
- x[(num+1)*ofs_x] = x[ofs_x];
- y[(num+0)*ofs_y] = y[0];
- y[(num+1)*ofs_y] = y[ofs_y];
- z[(num+0)*ofs_z] = z[0];
- z[(num+1)*ofs_z] = z[ofs_z];
- TReal sum_xy = 0.0, sum_yz = 0.0, sum_zx = 0.0;
- TReal *xptr = x +ofs_x, *xlow = x, *xhigh = x + ofs_x*2;
- TReal *yptr = y +ofs_y, *ylow = y, *yhigh = y + ofs_y*2;
- TReal *zptr = z +ofs_z, *zlow = z, *zhigh = z + ofs_z*2;
- for (int tmp=0; tmp < num; tmp++) {
- sum_xy += (*xptr) * ( (*yhigh) - (*ylow) );
- sum_yz += (*yptr) * ( (*zhigh) - (*zlow) );
- sum_zx += (*zptr) * ( (*xhigh) - (*xlow) );
- xptr += ofs_x;
- xlow += ofs_x;
- xhigh += ofs_x;
- yptr += ofs_y;
- ylow += ofs_y;
- yhigh += ofs_y;
- zptr += ofs_z;
- zlow += ofs_z;
- zhigh += ofs_z;
- }
- out = aiVector3t<TReal>(sum_yz,sum_zx,sum_xy);
- }
- } // ! namespace Assimp
- #endif // AI_POLYTOOLS_H_INCLUDED
|