|
|
//--------------------------------------------------------------------------------------------------
// qhMath.cpp
//
// Copyright(C) 2011 by D. Gregorius. All rights reserved.
//--------------------------------------------------------------------------------------------------
#include "qhMath.h"
//--------------------------------------------------------------------------------------------------
// Local utilities
//--------------------------------------------------------------------------------------------------
static inline qhBounds3 qhComputeBounds( const qhArray< qhVector3 >& Vertices, const qhTransform& Transform ) { qhBounds3 Bounds = QH_BOUNDS3_EMPTY; for ( int Index = 0; Index < Vertices.Size(); ++Index ) { Bounds += qhTMul( Transform, Vertices[ Index ] ); }
return Bounds; }
//--------------------------------------------------------------------------------------------------
// qhBox
//--------------------------------------------------------------------------------------------------
void qhBox::GetVertices( qhVector3 Vertices[ 8 ] ) const { Vertices[ 0 ] = Orientation * qhVector3( Extent.X, -Extent.Y, Extent.Z ) + Center; Vertices[ 1 ] = Orientation * qhVector3( -Extent.X, -Extent.Y, Extent.Z ) + Center; Vertices[ 2 ] = Orientation * qhVector3( -Extent.X, -Extent.Y, -Extent.Z ) + Center; Vertices[ 3 ] = Orientation * qhVector3( Extent.X, -Extent.Y, -Extent.Z ) + Center; Vertices[ 4 ] = Orientation * qhVector3( Extent.X, Extent.Y, Extent.Z ) + Center; Vertices[ 5 ] = Orientation * qhVector3( -Extent.X, Extent.Y, Extent.Z ) + Center; Vertices[ 6 ] = Orientation * qhVector3( -Extent.X, Extent.Y, -Extent.Z ) + Center; Vertices[ 7 ] = Orientation * qhVector3( Extent.X, Extent.Y, -Extent.Z ) + Center; }
//--------------------------------------------------------------------------------------------------
qhBox qhBestFit( const qhArray< qhVector3 >& Vertices, qhReal Threshold ) { qhVector3 Center( 0, 0, 0 ); for ( int Index = 0; Index < Vertices.Size(); ++Index ) { Center += Vertices[ Index ]; } Center = Center / float( Vertices.Size() );
qhBox BestBox; qhReal BestVolume = QH_REAL_MAX;
qhReal Sweep = qhReal( 45 ); qhVector3 SweepCenter( 0, 0, 0 );
while ( Sweep >= Threshold ) { bool Improved = false; qhVector3 BestAngles;
static const qhReal kSteps = 7.0; qhReal StepSize = Sweep / kSteps;
for ( qhReal X = SweepCenter.X - Sweep; X <= SweepCenter.X + Sweep; X += StepSize ) { for ( qhReal Y = SweepCenter.Y - Sweep; Y <= SweepCenter.Y + Sweep; Y += StepSize ) { for ( qhReal Z = SweepCenter.Z - Sweep; Z <= SweepCenter.Z + Sweep; Z += StepSize ) { qhQuaternion Rx = qhRotationX( X * QH_DEG2RAD ); qhQuaternion Ry = qhRotationY( Y * QH_DEG2RAD ); qhQuaternion Rz = qhRotationZ( Z * QH_DEG2RAD ); qhQuaternion R = Rz * Ry * Rx;
qhTransform Transform; Transform.Rotation = qhConvert( R ); Transform.Translation = Center;
qhBounds3 Bounds = qhComputeBounds( Vertices, Transform );
float Volume = Bounds.GetVolume(); if ( Volume < BestVolume ) { BestBox.Center = Transform * Bounds.GetCenter(); BestBox.Orientation = R; BestBox.Extent = Bounds.GetExtent();
BestVolume = Volume; BestAngles = qhVector3( X, Y, Z );
Improved = true; } } } }
if ( Improved ) { SweepCenter = BestAngles; Sweep *= 0.5f; } else { break; } }
return BestBox; }
//--------------------------------------------------------------------------------------------------
qhBox qhBestFit( int VertexCount, const void* VertexBase, int VertexStride, qhReal Threshold ) { qhArray< qhVector3 > Vertices; Vertices.Resize( VertexCount );
for ( int Index = 0; Index < VertexCount; ++Index ) { Vertices[ Index ] = qhVector3( reinterpret_cast< const qhReal* >( VertexBase ) ); VertexBase = qhAddByteOffset( VertexBase, VertexStride ); }
return qhBestFit( Vertices, Threshold ); }
|